Rev 6870 | Rev 6881 | Go to most recent revision | Only display areas with differences | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 6870 | Rev 6873 | ||
---|---|---|---|
1 | ; pngwrite.asm - general routines to write a PNG file |
1 | ; pngwrite.asm - general routines to write a PNG file |
2 | 2 | ||
3 | ; Last changed in libpng 1.6.24 [August 4, 2016] |
3 | ; Last changed in libpng 1.6.24 [August 4, 2016] |
4 | ; Copyright (c) 1998-2002,2004,2006-2016 Glenn Randers-Pehrson |
4 | ; Copyright (c) 1998-2002,2004,2006-2016 Glenn Randers-Pehrson |
5 | ; (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) |
5 | ; (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) |
6 | ; (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) |
6 | ; (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) |
7 | 7 | ||
8 | ; This code is released under the libpng license. |
8 | ; This code is released under the libpng license. |
9 | ; For conditions of distribution and use, see the disclaimer |
9 | ; For conditions of distribution and use, see the disclaimer |
10 | ; and license in png.inc |
10 | ; and license in png.inc |
11 | 11 | ||
12 | ; Write out all the unknown chunks for the current given location |
12 | ; Write out all the unknown chunks for the current given location |
13 | ;void (png_structrp png_ptr, png_const_inforp info_ptr, unsigned int where) |
13 | ;void (png_structrp png_ptr, png_const_inforp info_ptr, unsigned int where) |
14 | align 4 |
14 | align 4 |
15 | proc write_unknown_chunks, png_ptr:dword, info_ptr:dword, where:dword |
15 | proc write_unknown_chunks, png_ptr:dword, info_ptr:dword, where:dword |
16 | pushad |
16 | pushad |
17 | mov esi,[info_ptr] |
17 | mov esi,[info_ptr] |
18 | cmp dword[esi+png_info_def.unknown_chunks_num],0 |
18 | cmp dword[esi+png_info_def.unknown_chunks_num],0 |
19 | je .end_f ;if(..!=0) |
19 | je .end_f ;if(..!=0) |
20 | mov edi,[png_ptr] |
20 | mov edi,[png_ptr] |
21 | ;ecx = up |
21 | ;ecx = up |
22 | 22 | ||
23 | png_debug 5, 'writing extra chunks' |
23 | png_debug 5, 'writing extra chunks' |
24 | 24 | ||
25 | mov ecx,[esi+png_info_def.unknown_chunks] |
25 | mov ecx,[esi+png_info_def.unknown_chunks] |
26 | mov edx,[esi+png_info_def.unknown_chunks_num] |
26 | mov edx,[esi+png_info_def.unknown_chunks_num] |
27 | imul edx,sizeof.png_unknown_chunk |
27 | imul edx,sizeof.png_unknown_chunk |
28 | add edx,ecx |
28 | add edx,ecx |
29 | .cycle0: ;for (..;..<..;..) |
29 | .cycle0: ;for (..;..<..;..) |
30 | cmp ecx,edx |
30 | cmp ecx,edx |
31 | jge .end_f |
31 | jge .end_f |
32 | movzx eax,byte[ecx+png_unknown_chunk.location] |
32 | movzx eax,byte[ecx+png_unknown_chunk.location] |
33 | and eax,[where] |
33 | and eax,[where] |
34 | jz .end0 ;if (..!=0) |
34 | jz .end0 ;if (..!=0) |
35 | ; If per-chunk unknown chunk handling is enabled use it, otherwise |
35 | ; If per-chunk unknown chunk handling is enabled use it, otherwise |
36 | ; just write the chunks the application has set. |
36 | ; just write the chunks the application has set. |
37 | 37 | ||
38 | if PNG_SET_UNKNOWN_CHUNKS_SUPPORTED eq 1 |
38 | if PNG_SET_UNKNOWN_CHUNKS_SUPPORTED eq 1 |
39 | mov eax,ecx |
39 | mov eax,ecx |
40 | add eax,png_unknown_chunk.name |
40 | add eax,png_unknown_chunk.name |
41 | stdcall png_handle_as_unknown, edi, eax |
41 | stdcall png_handle_as_unknown, edi, eax |
42 | 42 | ||
43 | ; NOTE: this code is radically different from the read side in the |
43 | ; NOTE: this code is radically different from the read side in the |
44 | ; matter of handling an ancillary unknown chunk. In the read side |
44 | ; matter of handling an ancillary unknown chunk. In the read side |
45 | ; the default behavior is to discard it, in the code below the default |
45 | ; the default behavior is to discard it, in the code below the default |
46 | ; behavior is to write it. Critical chunks are, however, only |
46 | ; behavior is to write it. Critical chunks are, however, only |
47 | ; written if explicitly listed or if the default is set to write all |
47 | ; written if explicitly listed or if the default is set to write all |
48 | ; unknown chunks. |
48 | ; unknown chunks. |
49 | 49 | ||
50 | ; The default handling is also slightly weird - it is not possible to |
50 | ; The default handling is also slightly weird - it is not possible to |
51 | ; stop the writing of all unsafe-to-copy chunks! |
51 | ; stop the writing of all unsafe-to-copy chunks! |
52 | 52 | ||
53 | ; TODO: REVIEW: this would seem to be a bug. |
53 | ; TODO: REVIEW: this would seem to be a bug. |
54 | 54 | ||
55 | cmp eax,PNG_HANDLE_CHUNK_NEVER |
55 | cmp eax,PNG_HANDLE_CHUNK_NEVER |
56 | je .end0 |
56 | je .end0 |
57 | mov bl,byte[ecx+png_unknown_chunk.name+3] |
57 | mov bl,byte[ecx+png_unknown_chunk.name+3] |
58 | and bl,0x20 |
58 | and bl,0x20 |
59 | cmp bl,0 |
59 | cmp bl,0 |
60 | jne .beg0 |
60 | jne .beg0 |
61 | cmp eax,PNG_HANDLE_CHUNK_ALWAYS |
61 | cmp eax,PNG_HANDLE_CHUNK_ALWAYS |
62 | je .beg0 |
62 | je .beg0 |
63 | cmp eax,PNG_HANDLE_CHUNK_AS_DEFAULT |
63 | cmp eax,PNG_HANDLE_CHUNK_AS_DEFAULT |
64 | jne .end0 |
64 | jne .end0 |
65 | cmp dword[edi+png_struct.unknown_default],PNG_HANDLE_CHUNK_ALWAYS |
65 | cmp dword[edi+png_struct.unknown_default],PNG_HANDLE_CHUNK_ALWAYS |
66 | jne .end0 |
66 | jne .end0 |
67 | end if |
67 | end if |
68 | .beg0: ;if (..!=.. && (.. safe-to-copy overrides everything || ..==.. || (..==.. && ..==..))) |
68 | .beg0: ;if (..!=.. && (.. safe-to-copy overrides everything || ..==.. || (..==.. && ..==..))) |
69 | ; TODO: review, what is wrong with a zero length unknown chunk? |
69 | ; TODO: review, what is wrong with a zero length unknown chunk? |
70 | cmp dword[ecx+png_unknown_chunk.size],0 |
70 | cmp dword[ecx+png_unknown_chunk.size],0 |
71 | jne @f ;if (..==0) |
71 | jne @f ;if (..==0) |
72 | png_warning [png_ptr], 'Writing zero-length unknown chunk' |
72 | png_warning [png_ptr], 'Writing zero-length unknown chunk' |
73 | @@: |
73 | @@: |
74 | mov eax,dword[ecx+png_unknown_chunk.name] |
74 | mov eax,dword[ecx+png_unknown_chunk.name] |
75 | stdcall png_write_chunk, edi, eax, [ecx+png_unknown_chunk.podata], [ecx+png_unknown_chunk.size] |
75 | stdcall png_write_chunk, edi, eax, [ecx+png_unknown_chunk.podata], [ecx+png_unknown_chunk.size] |
76 | .end0: |
76 | .end0: |
77 | add ecx,sizeof.png_unknown_chunk |
77 | add ecx,sizeof.png_unknown_chunk |
78 | jmp .cycle0 |
78 | jmp .cycle0 |
79 | ;.cycle0end: |
79 | ;.cycle0end: |
80 | .end_f: |
80 | .end_f: |
81 | popad |
81 | popad |
82 | ret |
82 | ret |
83 | endp |
83 | endp |
84 | 84 | ||
85 | ; Writes all the PNG information. This is the suggested way to use the |
85 | ; Writes all the PNG information. This is the suggested way to use the |
86 | ; library. If you have a new chunk to add, make a function to write it, |
86 | ; library. If you have a new chunk to add, make a function to write it, |
87 | ; and put it in the correct location here. If you want the chunk written |
87 | ; and put it in the correct location here. If you want the chunk written |
88 | ; after the image data, put it in png_write_end(). I strongly encourage |
88 | ; after the image data, put it in png_write_end(). I strongly encourage |
89 | ; you to supply a PNG_INFO_ flag, and check info_ptr->valid before writing |
89 | ; you to supply a PNG_INFO_ flag, and check info_ptr->valid before writing |
90 | ; the chunk, as that will keep the code from breaking if you want to just |
90 | ; the chunk, as that will keep the code from breaking if you want to just |
91 | ; write a plain PNG file. If you have long comments, I suggest writing |
91 | ; write a plain PNG file. If you have long comments, I suggest writing |
92 | ; them in png_write_end(), and compressing them. |
92 | ; them in png_write_end(), and compressing them. |
93 | 93 | ||
94 | ;void (png_structrp png_ptr, png_const_inforp info_ptr) |
94 | ;void (png_structrp png_ptr, png_const_inforp info_ptr) |
95 | align 4 |
95 | align 4 |
96 | proc png_write_info_before_PLTE, png_ptr:dword, info_ptr:dword |
96 | proc png_write_info_before_PLTE, png_ptr:dword, info_ptr:dword |
97 | png_debug 1, 'in png_write_info_before_PLTE' |
97 | png_debug 1, 'in png_write_info_before_PLTE' |
98 | 98 | ||
99 | pushad |
99 | pushad |
100 | mov edi,[png_ptr] |
100 | mov edi,[png_ptr] |
101 | cmp edi,0 |
101 | cmp edi,0 |
102 | je .end_f |
102 | je .end_f |
103 | mov esi,[info_ptr] |
103 | mov esi,[info_ptr] |
104 | cmp esi,0 |
104 | cmp esi,0 |
105 | je .end_f ;if(..==0 || ..==0) return |
105 | je .end_f ;if(..==0 || ..==0) return |
106 | 106 | ||
107 | mov eax,[edi+png_struct.mode] |
107 | mov eax,[edi+png_struct.mode] |
108 | and eax,PNG_WROTE_INFO_BEFORE_PLTE |
108 | and eax,PNG_WROTE_INFO_BEFORE_PLTE |
109 | jnz .end_f ;if (..==0) |
109 | jnz .end_f ;if (..==0) |
110 | 110 | ||
111 | ; Write PNG signature |
111 | ; Write PNG signature |
112 | stdcall png_write_sig, edi |
112 | stdcall png_write_sig, edi |
113 | 113 | ||
114 | if PNG_MNG_FEATURES_SUPPORTED eq 1 |
114 | if PNG_MNG_FEATURES_SUPPORTED eq 1 |
115 | mov eax,[edi+png_struct.mode] |
115 | mov eax,[edi+png_struct.mode] |
116 | and eax,PNG_HAVE_PNG_SIGNATURE |
116 | and eax,PNG_HAVE_PNG_SIGNATURE |
117 | jz @f |
117 | jz @f |
118 | cmp dword[edi+png_struct.mng_features_permitted],0 |
118 | cmp dword[edi+png_struct.mng_features_permitted],0 |
119 | je @f ;if(..!=0 && ..!=0) |
119 | je @f ;if(..!=0 && ..!=0) |
120 | png_warning edi, 'MNG features are not allowed in a PNG datastream' |
120 | png_warning edi, 'MNG features are not allowed in a PNG datastream' |
121 | mov dword[edi+png_struct.mng_features_permitted],0 |
121 | mov dword[edi+png_struct.mng_features_permitted],0 |
122 | @@: |
122 | @@: |
123 | end if |
123 | end if |
124 | 124 | ||
125 | ; Write IHDR information. |
125 | ; Write IHDR information. |
126 | if PNG_WRITE_INTERLACING_SUPPORTED eq 1 |
126 | if PNG_WRITE_INTERLACING_SUPPORTED eq 1 |
127 | movzx eax,byte[esi+png_info_def.interlace_type] |
127 | movzx eax,byte[esi+png_info_def.interlace_type] |
128 | push eax |
128 | push eax |
129 | else |
129 | else |
130 | push dword 0 |
130 | push dword 0 |
131 | end if |
131 | end if |
132 | movzx eax,byte[esi+png_info_def.filter_type] |
132 | movzx eax,byte[esi+png_info_def.filter_type] |
133 | push eax |
133 | push eax |
134 | movzx eax,byte[esi+png_info_def.compression_type] |
134 | movzx eax,byte[esi+png_info_def.compression_type] |
135 | push eax |
135 | push eax |
136 | movzx eax,byte[esi+png_info_def.color_type] |
136 | movzx eax,byte[esi+png_info_def.color_type] |
137 | push eax |
137 | push eax |
138 | movzx eax,byte[esi+png_info_def.bit_depth] |
138 | movzx eax,byte[esi+png_info_def.bit_depth] |
139 | stdcall png_write_IHDR, edi,\ |
139 | stdcall png_write_IHDR, edi,\ |
140 | dword[esi+png_info_def.width], dword[esi+png_info_def.height], eax |
140 | dword[esi+png_info_def.width], dword[esi+png_info_def.height], eax |
141 | 141 | ||
142 | ; The rest of these check to see if the valid field has the appropriate |
142 | ; The rest of these check to see if the valid field has the appropriate |
143 | ; flag set, and if it does, writes the chunk. |
143 | ; flag set, and if it does, writes the chunk. |
144 | 144 | ||
145 | ; 1.6.0: COLORSPACE support controls the writing of these chunks too, and |
145 | ; 1.6.0: COLORSPACE support controls the writing of these chunks too, and |
146 | ; the chunks will be written if the WRITE routine is there and |
146 | ; the chunks will be written if the WRITE routine is there and |
147 | ; information * is available in the COLORSPACE. (See |
147 | ; information * is available in the COLORSPACE. (See |
148 | ; png_colorspace_sync_info in png.c for where the valid flags get set.) |
148 | ; png_colorspace_sync_info in png.c for where the valid flags get set.) |
149 | 149 | ||
150 | ; Under certain circumstances the colorspace can be invalidated without |
150 | ; Under certain circumstances the colorspace can be invalidated without |
151 | ; syncing the info_struct 'valid' flags; this happens if libpng detects |
151 | ; syncing the info_struct 'valid' flags; this happens if libpng detects |
152 | ; an error and calls png_error while the color space is being set, yet |
152 | ; an error and calls png_error while the color space is being set, yet |
153 | ; the application continues writing the PNG. So check the 'invalid' |
153 | ; the application continues writing the PNG. So check the 'invalid' |
154 | ; flag here too. |
154 | ; flag here too. |
155 | 155 | ||
156 | if PNG_GAMMA_SUPPORTED eq 1 |
156 | if PNG_GAMMA_SUPPORTED eq 1 |
157 | if PNG_WRITE_gAMA_SUPPORTED eq 1 |
157 | if PNG_WRITE_gAMA_SUPPORTED eq 1 |
158 | movzx eax,word[esi+png_info_def.colorspace.flags] |
158 | movzx eax,word[esi+png_info_def.colorspace.flags] |
159 | and eax,PNG_COLORSPACE_INVALID |
159 | and eax,PNG_COLORSPACE_INVALID |
160 | jnz @f |
160 | jnz @f |
161 | movzx eax,word[esi+png_info_def.colorspace.flags] |
161 | movzx eax,word[esi+png_info_def.colorspace.flags] |
162 | and eax,PNG_COLORSPACE_FROM_gAMA |
162 | and eax,PNG_COLORSPACE_FROM_gAMA |
163 | jz @f |
163 | jz @f |
164 | mov eax,[esi+png_info_def.valid] |
164 | mov eax,[esi+png_info_def.valid] |
165 | and eax,PNG_INFO_gAMA |
165 | and eax,PNG_INFO_gAMA |
166 | jz @f ;if (..==0 && ..!=0 && ..!=0) |
166 | jz @f ;if (..==0 && ..!=0 && ..!=0) |
167 | stdcall png_write_gAMA_fixed, edi, [esi+png_info_def.colorspace.gamma] |
167 | stdcall png_write_gAMA_fixed, edi, [esi+png_info_def.colorspace.gamma] |
168 | @@: |
168 | @@: |
169 | end if |
169 | end if |
170 | end if |
170 | end if |
171 | 171 | ||
172 | if PNG_COLORSPACE_SUPPORTED eq 1 |
172 | if PNG_COLORSPACE_SUPPORTED eq 1 |
173 | ; Write only one of sRGB or an ICC profile. If a profile was supplied |
173 | ; Write only one of sRGB or an ICC profile. If a profile was supplied |
174 | ; and it matches one of the known sRGB ones issue a warning. |
174 | ; and it matches one of the known sRGB ones issue a warning. |
175 | 175 | ||
176 | if PNG_WRITE_iCCP_SUPPORTED eq 1 |
176 | if PNG_WRITE_iCCP_SUPPORTED eq 1 |
177 | movzx eax,word[esi+png_info_def.colorspace.flags] |
177 | movzx eax,word[esi+png_info_def.colorspace.flags] |
178 | and eax,PNG_COLORSPACE_INVALID |
178 | and eax,PNG_COLORSPACE_INVALID |
179 | jnz .end0 |
179 | jnz .end0 |
180 | mov eax,[esi+png_info_def.valid] |
180 | mov eax,[esi+png_info_def.valid] |
181 | and eax,PNG_INFO_iCCP |
181 | and eax,PNG_INFO_iCCP |
182 | jz .end0 ;if (..==0 && ..!=0) |
182 | jz .end0 ;if (..==0 && ..!=0) |
183 | if PNG_WRITE_sRGB_SUPPORTED eq 1 |
183 | if PNG_WRITE_sRGB_SUPPORTED eq 1 |
184 | mov eax,[esi+png_info_def.valid] |
184 | mov eax,[esi+png_info_def.valid] |
185 | and eax,PNG_INFO_sRGB |
185 | and eax,PNG_INFO_sRGB |
186 | jz @f ;if (..!=0) |
186 | jz @f ;if (..!=0) |
187 | png_app_warning edi, 'profile matches sRGB but writing iCCP instead' |
187 | png_app_warning edi, 'profile matches sRGB but writing iCCP instead' |
188 | @@: |
188 | @@: |
189 | end if |
189 | end if |
190 | stdcall png_write_iCCP, edi, [esi+png_info_def.iccp_name],\ |
190 | stdcall png_write_iCCP, edi, [esi+png_info_def.iccp_name],\ |
191 | [esi+png_info_def.iccp_profile] |
191 | [esi+png_info_def.iccp_profile] |
192 | if PNG_WRITE_sRGB_SUPPORTED eq 1 |
192 | if PNG_WRITE_sRGB_SUPPORTED eq 1 |
193 | jmp .end1 |
193 | jmp .end1 |
194 | end if |
194 | end if |
195 | .end0: ;else |
195 | .end0: ;else |
196 | end if |
196 | end if |
197 | 197 | ||
198 | if PNG_WRITE_sRGB_SUPPORTED eq 1 |
198 | if PNG_WRITE_sRGB_SUPPORTED eq 1 |
199 | movzx eax,word[esi+png_info_def.colorspace.flags] |
199 | movzx eax,word[esi+png_info_def.colorspace.flags] |
200 | and eax,PNG_COLORSPACE_INVALID |
200 | and eax,PNG_COLORSPACE_INVALID |
201 | jnz .end1 |
201 | jnz .end1 |
202 | mov eax,[esi+png_info_def.valid] |
202 | mov eax,[esi+png_info_def.valid] |
203 | and eax,PNG_INFO_sRGB |
203 | and eax,PNG_INFO_sRGB |
204 | jz .end1 ;if (..==0 && ..!=0) |
204 | jz .end1 ;if (..==0 && ..!=0) |
205 | movzx eax,word[esi+png_info_def.colorspace.rendering_intent] |
205 | movzx eax,word[esi+png_info_def.colorspace.rendering_intent] |
206 | stdcall png_write_sRGB, edi, eax |
206 | stdcall png_write_sRGB, edi, eax |
207 | .end1: |
207 | .end1: |
208 | end if ;sRGB |
208 | end if ;sRGB |
209 | end if ;COLORSPACE |
209 | end if ;COLORSPACE |
210 | 210 | ||
211 | if PNG_WRITE_sBIT_SUPPORTED eq 1 |
211 | if PNG_WRITE_sBIT_SUPPORTED eq 1 |
212 | mov eax,[esi+png_info_def.valid] |
212 | mov eax,[esi+png_info_def.valid] |
213 | and eax,PNG_INFO_sBIT |
213 | and eax,PNG_INFO_sBIT |
214 | jz @f ;if (..!=0) |
214 | jz @f ;if (..!=0) |
215 | movzx eax,byte[esi+png_info_def.color_type] |
215 | movzx eax,byte[esi+png_info_def.color_type] |
216 | push eax |
216 | push eax |
217 | mov eax,esi |
217 | mov eax,esi |
218 | add eax,png_info_def.sig_bit |
218 | add eax,png_info_def.sig_bit |
219 | stdcall png_write_sBIT, edi, eax ;, ...color_type |
219 | stdcall png_write_sBIT, edi, eax ;, ...color_type |
220 | @@: |
220 | @@: |
221 | end if |
221 | end if |
222 | 222 | ||
223 | if PNG_COLORSPACE_SUPPORTED eq 1 |
223 | if PNG_COLORSPACE_SUPPORTED eq 1 |
224 | if PNG_WRITE_cHRM_SUPPORTED eq 1 |
224 | if PNG_WRITE_cHRM_SUPPORTED eq 1 |
225 | movzx eax,word[esi+png_info_def.colorspace.flags] |
225 | movzx eax,word[esi+png_info_def.colorspace.flags] |
226 | and eax,PNG_COLORSPACE_INVALID |
226 | and eax,PNG_COLORSPACE_INVALID |
227 | jnz @f |
227 | jnz @f |
228 | movzx eax,word[esi+png_info_def.colorspace.flags] |
228 | movzx eax,word[esi+png_info_def.colorspace.flags] |
229 | and eax,PNG_COLORSPACE_FROM_cHRM |
229 | and eax,PNG_COLORSPACE_FROM_cHRM |
230 | jz @f |
230 | jz @f |
231 | mov eax,[esi+png_info_def.valid] |
231 | mov eax,[esi+png_info_def.valid] |
232 | and eax,PNG_INFO_cHRM |
232 | and eax,PNG_INFO_cHRM |
233 | jz @f ;if (..==0 && ..!=0 && ..!=0) |
233 | jz @f ;if (..==0 && ..!=0 && ..!=0) |
234 | stdcall png_write_cHRM_fixed, edi, [esi+png_info_def.colorspace.end_points_xy] |
234 | stdcall png_write_cHRM_fixed, edi, [esi+png_info_def.colorspace.end_points_xy] |
235 | @@: |
235 | @@: |
236 | end if |
236 | end if |
237 | end if |
237 | end if |
238 | 238 | ||
239 | if PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED eq 1 |
239 | if PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED eq 1 |
240 | stdcall write_unknown_chunks, edi, esi, PNG_HAVE_IHDR |
240 | stdcall write_unknown_chunks, edi, esi, PNG_HAVE_IHDR |
241 | end if |
241 | end if |
242 | or dword[edi+png_struct.mode],PNG_WROTE_INFO_BEFORE_PLTE |
242 | or dword[edi+png_struct.mode],PNG_WROTE_INFO_BEFORE_PLTE |
243 | .end_f: |
243 | .end_f: |
244 | popad |
244 | popad |
245 | ret |
245 | ret |
246 | endp |
246 | endp |
247 | 247 | ||
248 | ;void (png_structrp png_ptr, png_const_inforp info_ptr) |
248 | ;void (png_structrp png_ptr, png_const_inforp info_ptr) |
249 | align 4 |
249 | align 4 |
250 | proc png_write_info, png_ptr:dword, info_ptr:dword |
250 | proc png_write_info, png_ptr:dword, info_ptr:dword |
251 | if (PNG_WRITE_TEXT_SUPPORTED eq 1) | (PNG_WRITE_sPLT_SUPPORTED eq 1) |
251 | if (PNG_WRITE_TEXT_SUPPORTED eq 1) | (PNG_WRITE_sPLT_SUPPORTED eq 1) |
252 | ; int i; |
252 | ; int i; |
253 | end if |
253 | end if |
254 | pushad |
254 | pushad |
255 | png_debug 1, 'in png_write_info' |
255 | png_debug 1, 'in png_write_info' |
256 | 256 | ||
257 | mov edi,[png_ptr] |
257 | mov edi,[png_ptr] |
258 | cmp edi,0 |
258 | cmp edi,0 |
259 | je .end_f |
259 | je .end_f |
260 | mov esi,[info_ptr] |
260 | mov esi,[info_ptr] |
261 | cmp esi,0 |
261 | cmp esi,0 |
262 | je .end_f ;if (..==0 || ..==0) return |
262 | je .end_f ;if (..==0 || ..==0) return |
263 | 263 | ||
264 | stdcall png_write_info_before_PLTE, edi, esi |
264 | stdcall png_write_info_before_PLTE, edi, esi |
265 | 265 | ||
266 | mov eax,[esi+png_info_def.valid] |
266 | mov eax,[esi+png_info_def.valid] |
267 | and eax,PNG_INFO_PLTE |
267 | and eax,PNG_INFO_PLTE |
268 | jz @f ;if (..!=0) |
268 | jz @f ;if (..!=0) |
269 | movzx eax,word[esi+png_info_def.num_palette] |
269 | movzx eax,word[esi+png_info_def.num_palette] |
270 | stdcall png_write_PLTE, edi, [esi+png_info_def.palette], eax |
270 | stdcall png_write_PLTE, edi, [esi+png_info_def.palette], eax |
271 | jmp .end_0 |
271 | jmp .end_0 |
272 | @@: |
272 | @@: |
273 | mov al,byte[esi+png_info_def.color_type] |
273 | mov al,byte[esi+png_info_def.color_type] |
274 | cmp al,PNG_COLOR_TYPE_PALETTE |
274 | cmp al,PNG_COLOR_TYPE_PALETTE |
275 | jne .end_0 ;else if (..==..) |
275 | jne .end_0 ;else if (..==..) |
276 | png_error edi, 'Valid palette required for paletted images' |
276 | png_error edi, 'Valid palette required for paletted images' |
277 | .end_0: |
277 | .end_0: |
278 | 278 | ||
279 | if PNG_WRITE_tRNS_SUPPORTED eq 1 |
279 | if PNG_WRITE_tRNS_SUPPORTED eq 1 |
280 | mov eax,[esi+png_info_def.valid] |
280 | mov eax,[esi+png_info_def.valid] |
281 | and eax,PNG_INFO_tRNS |
281 | and eax,PNG_INFO_tRNS |
282 | jz .end_1 ;if (..!=0) |
282 | jz .end_1 ;if (..!=0) |
283 | if PNG_WRITE_INVERT_ALPHA_SUPPORTED eq 1 |
283 | if PNG_WRITE_INVERT_ALPHA_SUPPORTED eq 1 |
284 | ; Invert the alpha channel (in tRNS) |
284 | ; Invert the alpha channel (in tRNS) |
285 | ; if ((png_ptr->transformations & PNG_INVERT_ALPHA) != 0 && |
285 | ; if ((png_ptr->transformations & PNG_INVERT_ALPHA) != 0 && |
286 | ; info_ptr->color_type == PNG_COLOR_TYPE_PALETTE) |
286 | ; info_ptr->color_type == PNG_COLOR_TYPE_PALETTE) |
287 | ; { |
287 | ; { |
288 | ; int j, jend; |
288 | ; int j, jend; |
289 | 289 | ||
290 | ; jend = info_ptr->num_trans; |
290 | ; jend = info_ptr->num_trans; |
291 | ; if (jend > PNG_MAX_PALETTE_LENGTH) |
291 | ; if (jend > PNG_MAX_PALETTE_LENGTH) |
292 | ; jend = PNG_MAX_PALETTE_LENGTH; |
292 | ; jend = PNG_MAX_PALETTE_LENGTH; |
293 | 293 | ||
294 | ; for (j = 0; j |
294 | ; for (j = 0; j |
295 | ; info_ptr->trans_alpha[j] = |
295 | ; info_ptr->trans_alpha[j] = |
296 | ; (byte)(255 - info_ptr->trans_alpha[j]); |
296 | ; (byte)(255 - info_ptr->trans_alpha[j]); |
297 | ; } |
297 | ; } |
298 | end if |
298 | end if |
299 | mov eax,esi |
299 | mov eax,esi |
300 | add eax,png_info_def.trans_color |
300 | add eax,png_info_def.trans_color |
301 | movzx ebx,word[esi+png_info_def.num_trans] |
301 | movzx ebx,word[esi+png_info_def.num_trans] |
302 | movzx ecx,byte[esi+png_info_def.color_type] |
302 | movzx ecx,byte[esi+png_info_def.color_type] |
303 | stdcall png_write_tRNS, edi, dword[esi+png_info_def.trans_alpha], eax, ebx, ecx |
303 | stdcall png_write_tRNS, edi, dword[esi+png_info_def.trans_alpha], eax, ebx, ecx |
304 | .end_1: |
304 | .end_1: |
305 | end if |
305 | end if |
306 | if PNG_WRITE_bKGD_SUPPORTED eq 1 |
306 | if PNG_WRITE_bKGD_SUPPORTED eq 1 |
307 | mov eax,[esi+png_info_def.valid] |
307 | mov eax,[esi+png_info_def.valid] |
308 | and eax,PNG_INFO_bKGD |
308 | and eax,PNG_INFO_bKGD |
309 | jz @f ;if (..!=0) |
309 | jz @f ;if (..!=0) |
310 | mov eax,esi |
310 | mov eax,esi |
311 | add eax,png_info_def.background |
311 | add eax,png_info_def.background |
312 | movzx ebx,byte[esi+png_info_def.color_type] |
312 | movzx ebx,byte[esi+png_info_def.color_type] |
313 | stdcall png_write_bKGD, edi, eax, ebx |
313 | stdcall png_write_bKGD, edi, eax, ebx |
314 | @@: |
314 | @@: |
315 | end if |
315 | end if |
316 | 316 | ||
317 | if PNG_WRITE_hIST_SUPPORTED eq 1 |
317 | if PNG_WRITE_hIST_SUPPORTED eq 1 |
318 | mov eax,[esi+png_info_def.valid] |
318 | mov eax,[esi+png_info_def.valid] |
319 | and eax,PNG_INFO_hIST |
319 | and eax,PNG_INFO_hIST |
320 | jz @f ;if (..!=0) |
320 | jz @f ;if (..!=0) |
321 | movzx ebx,word[esi+png_info_def.num_palette] |
321 | movzx ebx,word[esi+png_info_def.num_palette] |
322 | stdcall png_write_hIST, edi, [esi+png_info_def.hist], ebx |
322 | stdcall png_write_hIST, edi, [esi+png_info_def.hist], ebx |
323 | @@: |
323 | @@: |
324 | end if |
324 | end if |
325 | 325 | ||
326 | if PNG_WRITE_oFFs_SUPPORTED eq 1 |
326 | if PNG_WRITE_oFFs_SUPPORTED eq 1 |
327 | mov eax,[esi+png_info_def.valid] |
327 | mov eax,[esi+png_info_def.valid] |
328 | and eax,PNG_INFO_oFFs |
328 | and eax,PNG_INFO_oFFs |
329 | jz @f ;if (..!=0) |
329 | jz @f ;if (..!=0) |
330 | movzx ebx,byte[esi+png_info_def.offset_unit_type] |
330 | movzx ebx,byte[esi+png_info_def.offset_unit_type] |
331 | stdcall png_write_oFFs, edi, [esi+png_info_def.x_offset], [esi+png_info_def.y_offset], ebx |
331 | stdcall png_write_oFFs, edi, [esi+png_info_def.x_offset], [esi+png_info_def.y_offset], ebx |
332 | @@: |
332 | @@: |
333 | end if |
333 | end if |
334 | 334 | ||
335 | if PNG_WRITE_pCAL_SUPPORTED eq 1 |
335 | if PNG_WRITE_pCAL_SUPPORTED eq 1 |
336 | mov eax,[esi+png_info_def.valid] |
336 | mov eax,[esi+png_info_def.valid] |
337 | and eax,PNG_INFO_pCAL |
337 | and eax,PNG_INFO_pCAL |
338 | jz @f ;if (..!=0) |
338 | jz @f ;if (..!=0) |
339 | movzx ebx,byte[esi+png_info_def.pcal_type] |
339 | movzx ebx,byte[esi+png_info_def.pcal_type] |
340 | movzx ecx,byte[esi+png_info_def.pcal_nparams] |
340 | movzx ecx,byte[esi+png_info_def.pcal_nparams] |
341 | stdcall png_write_pCAL, edi, [esi+png_info_def.pcal_purpose], [esi+png_info_def.pcal_X0], [esi+png_info_def.pcal_X1], ebx, ecx, [esi+png_info_def.pcal_units], [esi+png_info_def.pcal_params] |
341 | stdcall png_write_pCAL, edi, [esi+png_info_def.pcal_purpose], [esi+png_info_def.pcal_X0], [esi+png_info_def.pcal_X1], ebx, ecx, [esi+png_info_def.pcal_units], [esi+png_info_def.pcal_params] |
342 | @@: |
342 | @@: |
343 | end if |
343 | end if |
344 | 344 | ||
345 | if PNG_WRITE_sCAL_SUPPORTED eq 1 |
345 | if PNG_WRITE_sCAL_SUPPORTED eq 1 |
346 | mov eax,[esi+png_info_def.valid] |
346 | mov eax,[esi+png_info_def.valid] |
347 | and eax,PNG_INFO_sCAL |
347 | and eax,PNG_INFO_sCAL |
348 | jz @f ;if (..!=0) |
348 | jz @f ;if (..!=0) |
349 | movzx ebx,byte[esi+png_info_def.scal_unit] |
349 | movzx ebx,byte[esi+png_info_def.scal_unit] |
350 | stdcall png_write_sCAL_s, edi, ebx, [esi+png_info_def.scal_s_width], [esi+png_info_def.scal_s_height] |
350 | stdcall png_write_sCAL_s, edi, ebx, [esi+png_info_def.scal_s_width], [esi+png_info_def.scal_s_height] |
351 | @@: |
351 | @@: |
352 | end if ;sCAL |
352 | end if ;sCAL |
353 | 353 | ||
354 | if PNG_WRITE_pHYs_SUPPORTED eq 1 |
354 | if PNG_WRITE_pHYs_SUPPORTED eq 1 |
355 | mov eax,[esi+png_info_def.valid] |
355 | mov eax,[esi+png_info_def.valid] |
356 | and eax,PNG_INFO_pHYs |
356 | and eax,PNG_INFO_pHYs |
357 | jz @f ;if (..!=0) |
357 | jz @f ;if (..!=0) |
358 | movzx ebx,byte[esi+png_info_def.phys_unit_type] |
358 | movzx ebx,byte[esi+png_info_def.phys_unit_type] |
359 | stdcall png_write_pHYs, edi, [esi+png_info_def.x_pixels_per_unit], [esi+png_info_def.y_pixels_per_unit], ebx |
359 | stdcall png_write_pHYs, edi, [esi+png_info_def.x_pixels_per_unit], [esi+png_info_def.y_pixels_per_unit], ebx |
360 | @@: |
360 | @@: |
361 | end if ;pHYs |
361 | end if ;pHYs |
362 | 362 | ||
363 | if PNG_WRITE_tIME_SUPPORTED eq 1 |
363 | if PNG_WRITE_tIME_SUPPORTED eq 1 |
364 | mov eax,[esi+png_info_def.valid] |
364 | mov eax,[esi+png_info_def.valid] |
365 | and eax,PNG_INFO_tIME |
365 | and eax,PNG_INFO_tIME |
366 | jz @f ;if (..!=0) |
366 | jz @f ;if (..!=0) |
367 | mov eax,esi |
367 | mov eax,esi |
368 | add eax,png_info_def.mod_time |
368 | add eax,png_info_def.mod_time |
369 | stdcall png_write_tIME, edi, eax |
369 | stdcall png_write_tIME, edi, eax |
370 | or [edi+png_struct.mode],PNG_WROTE_tIME |
370 | or [edi+png_struct.mode],PNG_WROTE_tIME |
371 | @@: |
371 | @@: |
372 | end if ;tIME |
372 | end if ;tIME |
373 | 373 | ||
374 | if PNG_WRITE_sPLT_SUPPORTED eq 1 |
374 | if PNG_WRITE_sPLT_SUPPORTED eq 1 |
375 | mov eax,[esi+png_info_def.valid] |
375 | mov eax,[esi+png_info_def.valid] |
376 | and eax,PNG_INFO_sPLT |
376 | and eax,PNG_INFO_sPLT |
377 | jz @f ;if (..!=0) |
377 | jz @f ;if (..!=0) |
378 | mov eax,[esi+png_info_def.splt_palettes] |
378 | mov eax,[esi+png_info_def.splt_palettes] |
379 | mov ecx,[esi+png_info_def.splt_palettes_num] |
379 | mov ecx,[esi+png_info_def.splt_palettes_num] |
380 | cmp ecx,1 |
380 | cmp ecx,1 |
381 | jl @f |
381 | jl @f |
382 | .cycle0: |
382 | .cycle0: |
383 | stdcall png_write_sPLT, edi, eax |
383 | stdcall png_write_sPLT, edi, eax |
384 | add eax,4 |
384 | add eax,4 |
385 | loop .cycle0 |
385 | loop .cycle0 |
386 | @@: |
386 | @@: |
387 | end if ;sPLT |
387 | end if ;sPLT |
388 | 388 | ||
389 | if PNG_WRITE_TEXT_SUPPORTED eq 1 |
389 | if PNG_WRITE_TEXT_SUPPORTED eq 1 |
390 | ; Check to see if we need to write text chunks |
390 | ; Check to see if we need to write text chunks |
391 | ; for (i = 0; i < info_ptr->num_text; i++) |
391 | ; for (i = 0; i < info_ptr->num_text; i++) |
392 | ; { |
392 | ; { |
393 | ; png_debug2(2, "Writing header text chunk %d, type %d", i, |
393 | ; png_debug2(2, "Writing header text chunk %d, type %d", i, |
394 | ; info_ptr->text[i].compression); |
394 | ; info_ptr->text[i].compression); |
395 | ; An internationalized chunk? |
395 | ; An internationalized chunk? |
396 | ; if (info_ptr->text[i].compression > 0) |
396 | ; if (info_ptr->text[i].compression > 0) |
397 | ; { |
397 | ; { |
398 | if PNG_WRITE_iTXt_SUPPORTED eq 1 |
398 | if PNG_WRITE_iTXt_SUPPORTED eq 1 |
399 | ; Write international chunk |
399 | ; Write international chunk |
400 | ; png_write_iTXt(png_ptr, |
400 | ; png_write_iTXt(png_ptr, |
401 | ; info_ptr->text[i].compression, |
401 | ; info_ptr->text[i].compression, |
402 | ; info_ptr->text[i].key, |
402 | ; info_ptr->text[i].key, |
403 | ; info_ptr->text[i].lang, |
403 | ; info_ptr->text[i].lang, |
404 | ; info_ptr->text[i].lang_key, |
404 | ; info_ptr->text[i].lang_key, |
405 | ; info_ptr->text[i].text); |
405 | ; info_ptr->text[i].text); |
406 | ; Mark this chunk as written |
406 | ; Mark this chunk as written |
407 | ; if (info_ptr->text[i].compression == PNG_TEXT_COMPRESSION_NONE) |
407 | ; if (info_ptr->text[i].compression == PNG_TEXT_COMPRESSION_NONE) |
408 | ; info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_NONE_WR; |
408 | ; info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_NONE_WR; |
409 | ; else |
409 | ; else |
410 | ; info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_zTXt_WR; |
410 | ; info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_zTXt_WR; |
411 | else |
411 | else |
412 | png_warning edi, 'Unable to write international text' |
412 | png_warning edi, 'Unable to write international text' |
413 | end if |
413 | end if |
414 | ; } |
414 | ; } |
415 | 415 | ||
416 | ; If we want a compressed text chunk |
416 | ; If we want a compressed text chunk |
417 | ; else if (info_ptr->text[i].compression == PNG_TEXT_COMPRESSION_zTXt) |
417 | ; else if (info_ptr->text[i].compression == PNG_TEXT_COMPRESSION_zTXt) |
418 | ; { |
418 | ; { |
419 | if PNG_WRITE_zTXt_SUPPORTED eq 1 |
419 | if PNG_WRITE_zTXt_SUPPORTED eq 1 |
420 | ; Write compressed chunk |
420 | ; Write compressed chunk |
421 | ; png_write_zTXt(png_ptr, info_ptr->text[i].key, |
421 | ; png_write_zTXt(png_ptr, info_ptr->text[i].key, |
422 | ; info_ptr->text[i].text, info_ptr->text[i].compression); |
422 | ; info_ptr->text[i].text, info_ptr->text[i].compression); |
423 | ; Mark this chunk as written |
423 | ; Mark this chunk as written |
424 | ; info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_zTXt_WR; |
424 | ; info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_zTXt_WR; |
425 | else |
425 | else |
426 | png_warning edi, 'Unable to write compressed text' |
426 | png_warning edi, 'Unable to write compressed text' |
427 | end if |
427 | end if |
428 | ; } |
428 | ; } |
429 | 429 | ||
430 | ; else if (info_ptr->text[i].compression == PNG_TEXT_COMPRESSION_NONE) |
430 | ; else if (info_ptr->text[i].compression == PNG_TEXT_COMPRESSION_NONE) |
431 | ; { |
431 | ; { |
432 | if PNG_WRITE_tEXt_SUPPORTED eq 1 |
432 | if PNG_WRITE_tEXt_SUPPORTED eq 1 |
433 | ; Write uncompressed chunk |
433 | ; Write uncompressed chunk |
434 | ; png_write_tEXt(png_ptr, info_ptr->text[i].key, |
434 | ; png_write_tEXt(png_ptr, info_ptr->text[i].key, |
435 | ; info_ptr->text[i].text, |
435 | ; info_ptr->text[i].text, |
436 | ; 0); |
436 | ; 0); |
437 | ; Mark this chunk as written |
437 | ; Mark this chunk as written |
438 | ; info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_NONE_WR; |
438 | ; info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_NONE_WR; |
439 | else |
439 | else |
440 | ; Can't get here |
440 | ; Can't get here |
441 | png_warning edi, 'Unable to write uncompressed text' |
441 | png_warning edi, 'Unable to write uncompressed text' |
442 | end if |
442 | end if |
443 | ; } |
443 | ; } |
444 | ; } |
444 | ; } |
445 | end if ;tEXt |
445 | end if ;tEXt |
446 | 446 | ||
447 | if PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED eq 1 |
447 | if PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED eq 1 |
448 | stdcall write_unknown_chunks, edi, esi, PNG_HAVE_PLTE |
448 | stdcall write_unknown_chunks, edi, esi, PNG_HAVE_PLTE |
449 | end if |
449 | end if |
450 | .end_f: |
450 | .end_f: |
451 | popad |
451 | popad |
452 | ret |
452 | ret |
453 | endp |
453 | endp |
454 | 454 | ||
455 | ; Writes the end of the PNG file. If you don't want to write comments or |
455 | ; Writes the end of the PNG file. If you don't want to write comments or |
456 | ; time information, you can pass NULL for info. If you already wrote these |
456 | ; time information, you can pass NULL for info. If you already wrote these |
457 | ; in png_write_info(), do not write them again here. If you have long |
457 | ; in png_write_info(), do not write them again here. If you have long |
458 | ; comments, I suggest writing them here, and compressing them. |
458 | ; comments, I suggest writing them here, and compressing them. |
459 | 459 | ||
460 | ;void (png_structrp png_ptr, png_inforp info_ptr) |
460 | ;void (png_structrp png_ptr, png_inforp info_ptr) |
461 | align 4 |
461 | align 4 |
462 | proc png_write_end, png_ptr:dword, info_ptr:dword |
462 | proc png_write_end, png_ptr:dword, info_ptr:dword |
463 | pushad |
463 | pushad |
464 | png_debug 1, 'in png_write_end' |
464 | png_debug 1, 'in png_write_end' |
465 | 465 | ||
466 | mov edi,[png_ptr] |
466 | mov edi,[png_ptr] |
467 | cmp edi,0 |
467 | cmp edi,0 |
468 | je .end_f ;if (..==0) return |
468 | je .end_f ;if (..==0) return |
469 | 469 | ||
470 | mov eax,[edi+png_struct.mode] |
470 | mov eax,[edi+png_struct.mode] |
471 | and eax,PNG_HAVE_IDAT |
471 | and eax,PNG_HAVE_IDAT |
472 | jnz @f ;if (..==0) |
472 | jnz @f ;if (..==0) |
473 | png_error edi, 'No IDATs written into file' |
473 | png_error edi, 'No IDATs written into file' |
474 | @@: |
474 | @@: |
475 | 475 | ||
476 | if PNG_WRITE_CHECK_FOR_INVALID_INDEX_SUPPORTED eq 1 |
476 | if PNG_WRITE_CHECK_FOR_INVALID_INDEX_SUPPORTED eq 1 |
477 | mov eax,[edi+png_struct.num_palette_max] |
477 | mov eax,[edi+png_struct.num_palette_max] |
478 | cmp ax,[edi+png_struct.num_palette] |
478 | cmp ax,[edi+png_struct.num_palette] |
479 | jle @f ;if (..>..) |
479 | jle @f ;if (..>..) |
480 | png_benign_error edi, 'Wrote palette index exceeding num_palette' |
480 | png_benign_error edi, 'Wrote palette index exceeding num_palette' |
481 | @@: |
481 | @@: |
482 | end if |
482 | end if |
483 | 483 | ||
484 | ; See if user wants us to write information chunks |
484 | ; See if user wants us to write information chunks |
485 | mov esi,[info_ptr] |
485 | mov esi,[info_ptr] |
486 | cmp esi,0 |
486 | cmp esi,0 |
487 | je .end0 ;if (..!=0) |
487 | je .end0 ;if (..!=0) |
488 | if PNG_WRITE_TEXT_SUPPORTED eq 1 |
488 | if PNG_WRITE_TEXT_SUPPORTED eq 1 |
489 | ; int i; /* local index variable */ |
489 | ; int i; /* local index variable */ |
490 | end if |
490 | end if |
491 | if PNG_WRITE_tIME_SUPPORTED eq 1 |
491 | if PNG_WRITE_tIME_SUPPORTED eq 1 |
492 | ; Check to see if user has supplied a time chunk |
492 | ; Check to see if user has supplied a time chunk |
493 | mov eax,[esi+png_info_def.valid] |
493 | mov eax,[esi+png_info_def.valid] |
494 | and eax,PNG_INFO_tIME |
494 | and eax,PNG_INFO_tIME |
495 | jz @f |
495 | jz @f |
496 | mov eax,[edi+png_struct.mode] |
496 | mov eax,[edi+png_struct.mode] |
497 | and eax,PNG_WROTE_tIME |
497 | and eax,PNG_WROTE_tIME |
498 | jnz @f ;if (..!=0 && ..==0) |
498 | jnz @f ;if (..!=0 && ..==0) |
499 | mov eax,esi |
499 | mov eax,esi |
500 | add eax,png_info_def.mod_time |
500 | add eax,png_info_def.mod_time |
501 | stdcall png_write_tIME, edi, eax |
501 | stdcall png_write_tIME, edi, eax |
502 | @@: |
502 | @@: |
503 | 503 | ||
504 | end if |
504 | end if |
505 | if PNG_WRITE_TEXT_SUPPORTED eq 1 |
505 | if PNG_WRITE_TEXT_SUPPORTED eq 1 |
506 | ; Loop through comment chunks |
506 | ; Loop through comment chunks |
507 | cmp dword[esi+png_info_def.num_text],0 |
507 | cmp dword[esi+png_info_def.num_text],0 |
508 | jle .cycle0end |
508 | jle .cycle0end |
509 | xor ecx,ecx |
509 | xor ecx,ecx |
510 | align 4 |
510 | align 4 |
511 | .cycle0: ;for (i = 0; i < info_ptr->num_text; i++) |
511 | .cycle0: ;for (i = 0; i < info_ptr->num_text; i++) |
512 | 512 | ||
513 | ; png_debug2(2, "Writing trailer text chunk %d, type %d", i, |
513 | ; png_debug2(2, "Writing trailer text chunk %d, type %d", i, |
514 | ; info_ptr->text[i].compression); |
514 | ; info_ptr->text[i].compression); |
515 | ; An internationalized chunk? |
515 | ; An internationalized chunk? |
516 | mov eax,ecx |
516 | mov eax,ecx |
517 | shl eax,2 |
517 | shl eax,2 |
518 | add eax,[esi+png_info_def.text] ;eax = info_ptr.text[i] |
518 | add eax,[esi+png_info_def.text] ;eax = info_ptr.text[i] |
519 | cmp dword[eax+png_text.compression],0 |
519 | cmp dword[eax+png_text.compression],0 |
520 | jle .end1 ;if (info_ptr.text[i].compression > 0) |
520 | jle .end1 ;if (info_ptr.text[i].compression > 0) |
521 | if PNG_WRITE_iTXt_SUPPORTED eq 1 |
521 | if PNG_WRITE_iTXt_SUPPORTED eq 1 |
522 | ; Write international chunk |
522 | ; Write international chunk |
523 | stdcall png_write_iTXt, edi,\ |
523 | stdcall png_write_iTXt, edi,\ |
524 | [eax+png_text.compression],\ |
524 | [eax+png_text.compression],\ |
525 | [eax+png_text.key],\ |
525 | [eax+png_text.key],\ |
526 | [eax+png_text.lang],\ |
526 | [eax+png_text.lang],\ |
527 | [eax+png_text.lang_key],\ |
527 | [eax+png_text.lang_key],\ |
528 | [eax+png_text.text] |
528 | [eax+png_text.text] |
529 | ; Mark this chunk as written |
529 | ; Mark this chunk as written |
530 | mov ebx,PNG_TEXT_COMPRESSION_zTXt_WR |
530 | mov ebx,PNG_TEXT_COMPRESSION_zTXt_WR |
531 | cmp dword[eax+png_text.compression],PNG_TEXT_COMPRESSION_NONE |
531 | cmp dword[eax+png_text.compression],PNG_TEXT_COMPRESSION_NONE |
532 | jne @f |
532 | jne @f |
533 | mov ebx,PNG_TEXT_COMPRESSION_NONE_WR |
533 | mov ebx,PNG_TEXT_COMPRESSION_NONE_WR |
534 | @@: |
534 | @@: |
535 | mov dword[eax+png_text.compression],ebx |
535 | mov dword[eax+png_text.compression],ebx |
536 | else |
536 | else |
537 | png_warning edi, 'Unable to write international text' |
537 | png_warning edi, 'Unable to write international text' |
538 | end if |
538 | end if |
539 | jmp .end3 |
539 | jmp .end3 |
540 | .end1: |
540 | .end1: |
541 | cmp dword[eax+png_text.compression],PNG_TEXT_COMPRESSION_zTXt |
541 | cmp dword[eax+png_text.compression],PNG_TEXT_COMPRESSION_zTXt |
542 | jl .end2 ;else if (info_ptr.text[i].compression >= ..) |
542 | jl .end2 ;else if (info_ptr.text[i].compression >= ..) |
543 | if PNG_WRITE_zTXt_SUPPORTED eq 1 |
543 | if PNG_WRITE_zTXt_SUPPORTED eq 1 |
544 | ; Write compressed chunk |
544 | ; Write compressed chunk |
545 | stdcall png_write_zTXt, edi, [eax+png_text.key],\ |
545 | stdcall png_write_zTXt, edi, [eax+png_text.key],\ |
546 | [eax+png_text.text], [eax+png_text.compression] |
546 | [eax+png_text.text], [eax+png_text.compression] |
547 | ; Mark this chunk as written |
547 | ; Mark this chunk as written |
548 | mov dword[eax+png_text.compression],PNG_TEXT_COMPRESSION_zTXt_WR |
548 | mov dword[eax+png_text.compression],PNG_TEXT_COMPRESSION_zTXt_WR |
549 | else |
549 | else |
550 | png_warning edi, 'Unable to write compressed text' |
550 | png_warning edi, 'Unable to write compressed text' |
551 | end if |
551 | end if |
552 | jmp .end3 |
552 | jmp .end3 |
553 | .end2: |
553 | .end2: |
554 | cmp dword[eax+png_text.compression],PNG_TEXT_COMPRESSION_NONE |
554 | cmp dword[eax+png_text.compression],PNG_TEXT_COMPRESSION_NONE |
555 | jl .end3 ;else if (info_ptr.text[i].compression == ..) |
555 | jl .end3 ;else if (info_ptr.text[i].compression == ..) |
556 | if PNG_WRITE_tEXt_SUPPORTED eq 1 |
556 | if PNG_WRITE_tEXt_SUPPORTED eq 1 |
557 | ; Write uncompressed chunk |
557 | ; Write uncompressed chunk |
558 | stdcall png_write_tEXt, edi, [eax+png_text.key],\ |
558 | stdcall png_write_tEXt, edi, [eax+png_text.key],\ |
559 | [eax+png_text.text], 0 |
559 | [eax+png_text.text], 0 |
560 | ; Mark this chunk as written |
560 | ; Mark this chunk as written |
561 | mov dword[eax+png_text.compression],PNG_TEXT_COMPRESSION_NONE_WR |
561 | mov dword[eax+png_text.compression],PNG_TEXT_COMPRESSION_NONE_WR |
562 | else |
562 | else |
563 | png_warning edi, 'Unable to write uncompressed text' |
563 | png_warning edi, 'Unable to write uncompressed text' |
564 | end if |
564 | end if |
565 | .end3: |
565 | .end3: |
566 | 566 | ||
567 | inc ecx |
567 | inc ecx |
568 | cmp ecx,[esi+png_info_def.num_text] |
568 | cmp ecx,[esi+png_info_def.num_text] |
569 | jl .cycle0 |
569 | jl .cycle0 |
570 | .cycle0end: |
570 | .cycle0end: |
571 | end if |
571 | end if |
572 | if PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED eq 1 |
572 | if PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED eq 1 |
573 | stdcall write_unknown_chunks, edi, esi, PNG_AFTER_IDAT |
573 | stdcall write_unknown_chunks, edi, esi, PNG_AFTER_IDAT |
574 | end if |
574 | end if |
575 | .end0: |
575 | .end0: |
576 | 576 | ||
577 | or dword[edi+png_struct.mode], PNG_AFTER_IDAT |
577 | or dword[edi+png_struct.mode], PNG_AFTER_IDAT |
578 | 578 | ||
579 | ; Write end of PNG file |
579 | ; Write end of PNG file |
580 | stdcall png_write_IEND, edi |
580 | stdcall png_write_IEND, edi |
581 | 581 | ||
582 | ; This flush, added in libpng-1.0.8, removed from libpng-1.0.9beta03, |
582 | ; This flush, added in libpng-1.0.8, removed from libpng-1.0.9beta03, |
583 | ; and restored again in libpng-1.2.30, may cause some applications that |
583 | ; and restored again in libpng-1.2.30, may cause some applications that |
584 | ; do not set png_ptr->output_flush_fn to crash. If your application |
584 | ; do not set png_ptr->output_flush_fn to crash. If your application |
585 | ; experiences a problem, please try building libpng with |
585 | ; experiences a problem, please try building libpng with |
586 | ; PNG_WRITE_FLUSH_AFTER_IEND_SUPPORTED defined, and report the event to |
586 | ; PNG_WRITE_FLUSH_AFTER_IEND_SUPPORTED defined, and report the event to |
587 | ; png-mng-implement at lists.sf.net . |
587 | ; png-mng-implement at lists.sf.net . |
588 | 588 | ||
589 | if PNG_WRITE_FLUSH_SUPPORTED eq 1 |
589 | if PNG_WRITE_FLUSH_SUPPORTED eq 1 |
590 | if PNG_WRITE_FLUSH_AFTER_IEND_SUPPORTED eq 1 |
590 | if PNG_WRITE_FLUSH_AFTER_IEND_SUPPORTED eq 1 |
591 | stdcall png_flush, edi |
591 | stdcall png_flush, edi |
592 | end if |
592 | end if |
593 | end if |
593 | end if |
594 | .end_f: |
594 | .end_f: |
595 | popad |
595 | popad |
596 | ret |
596 | ret |
597 | endp |
597 | endp |
598 | 598 | ||
599 | ;void (png_timep ptime, struct tm * ttime) |
599 | ;void (png_timep ptime, struct tm * ttime) |
600 | align 4 |
600 | align 4 |
601 | proc png_convert_from_struct_tm, ptime:dword, ttime:dword |
601 | proc png_convert_from_struct_tm, ptime:dword, ttime:dword |
602 | png_debug 1, 'in png_convert_from_struct_tm' |
602 | png_debug 1, 'in png_convert_from_struct_tm' |
603 | 603 | ||
604 | ; ptime->year = (uint_16)(1900 + ttime->tm_year); |
604 | ; ptime->year = (uint_16)(1900 + ttime->tm_year); |
605 | ; ptime->month = (byte)(ttime->tm_mon + 1); |
605 | ; ptime->month = (byte)(ttime->tm_mon + 1); |
606 | ; ptime->day = (byte)ttime->tm_mday; |
606 | ; ptime->day = (byte)ttime->tm_mday; |
607 | ; ptime->hour = (byte)ttime->tm_hour; |
607 | ; ptime->hour = (byte)ttime->tm_hour; |
608 | ; ptime->minute = (byte)ttime->tm_min; |
608 | ; ptime->minute = (byte)ttime->tm_min; |
609 | ; ptime->second = (byte)ttime->tm_sec; |
609 | ; ptime->second = (byte)ttime->tm_sec; |
610 | ret |
610 | ret |
611 | endp |
611 | endp |
612 | 612 | ||
613 | ;void (png_timep ptime, time_t ttime) |
613 | ;void (png_timep ptime, time_t ttime) |
614 | align 4 |
614 | align 4 |
615 | proc png_convert_from_time_t, ptime:dword, ttime:dword |
615 | proc png_convert_from_time_t, ptime:dword, ttime:dword |
616 | ; struct tm *tbuf; |
616 | ; struct tm *tbuf; |
617 | 617 | ||
618 | png_debug 1, 'in png_convert_from_time_t' |
618 | png_debug 1, 'in png_convert_from_time_t' |
619 | 619 | ||
620 | ; tbuf = gmtime(&ttime); |
620 | ; tbuf = gmtime(&ttime); |
621 | ; png_convert_from_struct_tm(ptime, tbuf); |
621 | ; png_convert_from_struct_tm(ptime, tbuf); |
622 | ret |
622 | ret |
623 | endp |
623 | endp |
624 | 624 | ||
625 | ; Initialize png_ptr structure, and allocate any memory needed |
625 | ; Initialize png_ptr structure, and allocate any memory needed |
626 | ;png_structp (charp user_png_ver, voidp error_ptr, png_error_ptr error_fn, png_error_ptr warn_fn) |
626 | ;png_structp (charp user_png_ver, voidp error_ptr, png_error_ptr error_fn, png_error_ptr warn_fn) |
627 | align 4 |
627 | align 4 |
628 | proc png_create_write_struct, user_png_ver:dword, error_ptr:dword, error_fn:dword, warn_fn:dword |
628 | proc png_create_write_struct, user_png_ver:dword, error_ptr:dword, error_fn:dword, warn_fn:dword |
629 | if PNG_USER_MEM_SUPPORTED eq 1 |
629 | if PNG_USER_MEM_SUPPORTED eq 1 |
630 | stdcall png_create_png_struct, [user_png_ver], [error_ptr], [error_fn], [warn_fn], 0, 0, 0 |
630 | stdcall png_create_png_struct, [user_png_ver], [error_ptr], [error_fn], [warn_fn], 0, 0, 0 |
631 | ;eax = png_ptr |
631 | ;eax = png_ptr |
632 | end if ;USER_MEM |
632 | end if ;USER_MEM |
633 | cmp eax,0 |
633 | cmp eax,0 |
634 | je .end0 ;if (..!=0) |
634 | je .end0 ;if (..!=0) |
635 | ; Set the zlib control values to defaults; they can be overridden by the |
635 | ; Set the zlib control values to defaults; they can be overridden by the |
636 | ; application after the struct has been created. |
636 | ; application after the struct has been created. |
637 | 637 | ||
638 | mov dword[eax+png_struct.zbuffer_size], PNG_ZBUF_SIZE |
638 | mov dword[eax+png_struct.zbuffer_size], PNG_ZBUF_SIZE |
639 | 639 | ||
640 | ; The 'zlib_strategy' setting is irrelevant because png_default_claim in |
640 | ; The 'zlib_strategy' setting is irrelevant because png_default_claim in |
641 | ; pngwutil.asm defaults it according to whether or not filters will be |
641 | ; pngwutil.asm defaults it according to whether or not filters will be |
642 | ; used, and ignores this setting. |
642 | ; used, and ignores this setting. |
643 | 643 | ||
644 | mov dword[eax+png_struct.zlib_strategy], PNG_Z_DEFAULT_STRATEGY |
644 | mov dword[eax+png_struct.zlib_strategy], PNG_Z_DEFAULT_STRATEGY |
645 | mov dword[eax+png_struct.zlib_level], PNG_Z_DEFAULT_COMPRESSION |
645 | mov dword[eax+png_struct.zlib_level], PNG_Z_DEFAULT_COMPRESSION |
646 | mov dword[eax+png_struct.zlib_mem_level], 8 |
646 | mov dword[eax+png_struct.zlib_mem_level], 8 |
647 | mov dword[eax+png_struct.zlib_window_bits], 15 |
647 | mov dword[eax+png_struct.zlib_window_bits], 15 |
648 | mov dword[eax+png_struct.zlib_method], 8 |
648 | mov dword[eax+png_struct.zlib_method], 8 |
649 | 649 | ||
650 | if PNG_WRITE_COMPRESSED_TEXT_SUPPORTED eq 1 |
650 | if PNG_WRITE_COMPRESSED_TEXT_SUPPORTED eq 1 |
651 | mov dword[eax+png_struct.zlib_text_strategy], PNG_TEXT_Z_DEFAULT_STRATEGY |
651 | mov dword[eax+png_struct.zlib_text_strategy], PNG_TEXT_Z_DEFAULT_STRATEGY |
652 | mov dword[eax+png_struct.zlib_text_level], PNG_TEXT_Z_DEFAULT_COMPRESSION |
652 | mov dword[eax+png_struct.zlib_text_level], PNG_TEXT_Z_DEFAULT_COMPRESSION |
653 | mov dword[eax+png_struct.zlib_text_mem_level], 8 |
653 | mov dword[eax+png_struct.zlib_text_mem_level], 8 |
654 | mov dword[eax+png_struct.zlib_text_window_bits], 15 |
654 | mov dword[eax+png_struct.zlib_text_window_bits], 15 |
655 | mov dword[eax+png_struct.zlib_text_method], 8 |
655 | mov dword[eax+png_struct.zlib_text_method], 8 |
656 | end if |
656 | end if |
657 | ; This is a highly dubious configuration option; by default it is off, |
657 | ; This is a highly dubious configuration option; by default it is off, |
658 | ; but it may be appropriate for private builds that are testing |
658 | ; but it may be appropriate for private builds that are testing |
659 | ; extensions not conformant to the current specification, or of |
659 | ; extensions not conformant to the current specification, or of |
660 | ; applications that must not fail to write at all costs! |
660 | ; applications that must not fail to write at all costs! |
661 | 661 | ||
662 | if PNG_BENIGN_WRITE_ERRORS_SUPPORTED eq 1 |
662 | if PNG_BENIGN_WRITE_ERRORS_SUPPORTED eq 1 |
663 | ; In stable builds only warn if an application error can be completely |
663 | ; In stable builds only warn if an application error can be completely |
664 | ; handled. |
664 | ; handled. |
665 | 665 | ||
666 | or dword[eax+png_struct.flags], PNG_FLAG_BENIGN_ERRORS_WARN |
666 | or dword[eax+png_struct.flags], PNG_FLAG_BENIGN_ERRORS_WARN |
667 | end if |
667 | end if |
668 | ; App warnings are warnings in release (or release candidate) builds but |
668 | ; App warnings are warnings in release (or release candidate) builds but |
669 | ; are errors during development. |
669 | ; are errors during development. |
670 | 670 | ||
671 | if PNG_RELEASE_BUILD eq 1 |
671 | if PNG_RELEASE_BUILD eq 1 |
672 | or dword[eax+png_struct.flags], PNG_FLAG_APP_WARNINGS_WARN |
672 | or dword[eax+png_struct.flags], PNG_FLAG_APP_WARNINGS_WARN |
673 | end if |
673 | end if |
674 | ; TODO: delay this, it can be done in png_init_io() (if the app doesn't |
674 | ; TODO: delay this, it can be done in png_init_io() (if the app doesn't |
675 | ; do it itself) avoiding setting the default function if it is not |
675 | ; do it itself) avoiding setting the default function if it is not |
676 | ; required. |
676 | ; required. |
677 | 677 | ||
678 | stdcall png_set_write_fn, eax, 0, 0, 0 |
678 | stdcall png_set_write_fn, eax, 0, 0, 0 |
679 | .end0: |
679 | .end0: |
680 | ret |
680 | ret |
681 | endp |
681 | endp |
682 | 682 | ||
683 | 683 | ||
684 | ; Write a few rows of image data. If the image is interlaced, |
684 | ; Write a few rows of image data. If the image is interlaced, |
685 | ; either you will have to write the 7 sub images, or, if you |
685 | ; either you will have to write the 7 sub images, or, if you |
686 | ; have called png_set_interlace_handling(), you will have to |
686 | ; have called png_set_interlace_handling(), you will have to |
687 | ; "write" the image seven times. |
687 | ; "write" the image seven times. |
688 | 688 | ||
689 | ;void (png_structrp png_ptr, bytepp row, uint_32 num_rows) |
689 | ;void (png_structrp png_ptr, bytepp row, uint_32 num_rows) |
690 | align 4 |
690 | align 4 |
691 | proc png_write_rows uses ebx ecx edi, png_ptr:dword, row:dword, num_rows:dword |
691 | proc png_write_rows uses ebx ecx edi, png_ptr:dword, row:dword, num_rows:dword |
692 | ;locals |
692 | ;locals |
693 | ;i dd ? ;uint_32 ;row counter |
693 | ;i dd ? ;uint_32 ;row counter |
694 | ;rp dd ? ;bytepp ;row pointer |
694 | ;rp dd ? ;bytepp ;row pointer |
695 | ;endl |
695 | ;endl |
696 | png_debug 1, 'in png_write_rows' |
696 | png_debug 1, 'in png_write_rows' |
697 | 697 | ||
698 | mov edi,[png_ptr] |
698 | mov edi,[png_ptr] |
699 | cmp edi,0 |
699 | cmp edi,0 |
700 | je .end_f ;if(..==0) return |
700 | je .end_f ;if(..==0) return |
701 | 701 | ||
702 | ; Loop through the rows |
702 | ; Loop through the rows |
703 | mov ecx,[num_rows] |
703 | mov ecx,[num_rows] |
704 | cmp ecx,1 |
704 | cmp ecx,1 |
705 | jl .end_f |
705 | jl .end_f |
706 | mov ebx,[row] |
706 | mov ebx,[row] |
707 | @@: ;for (i = 0, rp = row; i < num_rows; i++, rp++) |
707 | @@: ;for (i = 0, rp = row; i < num_rows; i++, rp++) |
708 | stdcall png_write_row, edi, [ebx] |
708 | stdcall png_write_row, edi, [ebx] |
709 | add ebx,4 |
709 | add ebx,4 |
710 | loop @b |
710 | loop @b |
711 | .end_f: |
711 | .end_f: |
712 | ret |
712 | ret |
713 | endp |
713 | endp |
714 | 714 | ||
715 | ; Write the image. You only need to call this function once, even |
715 | ; Write the image. You only need to call this function once, even |
716 | ; if you are writing an interlaced image. |
716 | ; if you are writing an interlaced image. |
717 | 717 | ||
718 | ;void (png_structrp png_ptr, bytepp image) |
718 | ;void (png_structrp png_ptr, bytepp image) |
719 | align 4 |
719 | align 4 |
720 | proc png_write_image, png_ptr:dword, image:dword |
720 | proc png_write_image, png_ptr:dword, image:dword |
721 | pushad |
721 | pushad |
722 | ;ebx ;bytepp ;points to current row |
722 | ;ebx ;bytepp ;points to current row |
723 | ;ecx ;uint_32 ;row index |
723 | ;ecx ;uint_32 ;row index |
724 | ;edx ;int ;pass |
724 | ;edx ;int ;pass |
725 | ;esi ;int ;num_pass |
725 | ;esi ;int ;num_pass |
726 | mov edi,[png_ptr] |
726 | mov edi,[png_ptr] |
727 | cmp edi,0 |
727 | cmp edi,0 |
728 | je .end_f ;if (..==0) return |
728 | je .end_f ;if (..==0) return |
729 | 729 | ||
730 | png_debug 1, 'in png_write_image' |
730 | png_debug 1, 'in png_write_image' |
731 | 731 | ||
732 | if PNG_WRITE_INTERLACING_SUPPORTED eq 1 |
732 | if PNG_WRITE_INTERLACING_SUPPORTED eq 1 |
733 | ; Initialize interlace handling. If image is not interlaced, |
733 | ; Initialize interlace handling. If image is not interlaced, |
734 | ; this will set pass to 1 |
734 | ; this will set pass to 1 |
735 | 735 | ||
736 | stdcall png_set_interlace_handling, edi |
736 | stdcall png_set_interlace_handling, edi |
737 | mov esi,eax |
737 | mov esi,eax |
738 | else |
738 | else |
739 | xor esi,esi |
739 | xor esi,esi |
740 | inc esi |
740 | inc esi |
741 | end if |
741 | end if |
742 | ; Loop through passes |
742 | ; Loop through passes |
743 | xor edx,edx |
743 | xor edx,edx |
744 | .cycle0: ;for (edx = 0; edx < esi; edx++) |
744 | .cycle0: ;for (edx = 0; edx < esi; edx++) |
745 | cmp edx,esi |
745 | cmp edx,esi |
746 | jge .cycle0end |
746 | jge .cycle0end |
747 | ; Loop through image |
747 | ; Loop through image |
748 | mov ebx,[image] |
748 | mov ebx,[image] |
749 | xor ecx,ecx |
749 | xor ecx,ecx |
750 | .cycle1: ;for (ecx = 0, ebx = image; ecx < png_ptr.height; ecx++, ebx++) |
750 | .cycle1: ;for (ecx = 0, ebx = image; ecx < png_ptr.height; ecx++, ebx++) |
751 | stdcall png_write_row, edi,[ebx] |
751 | stdcall png_write_row, edi,[ebx] |
752 | inc ecx |
752 | inc ecx |
753 | add ebx,4 |
753 | add ebx,4 |
754 | cmp ecx,[edi+png_struct.height] |
754 | cmp ecx,[edi+png_struct.height] |
755 | jl .cycle1 |
755 | jl .cycle1 |
756 | ;.cycle1end: |
756 | ;.cycle1end: |
757 | inc edx |
757 | inc edx |
758 | jmp .cycle0 |
758 | jmp .cycle0 |
759 | .cycle0end: |
759 | .cycle0end: |
760 | .end_f: |
760 | .end_f: |
761 | popad |
761 | popad |
762 | ret |
762 | ret |
763 | endp |
763 | endp |
764 | 764 | ||
765 | ; Performs intrapixel differencing |
765 | ; Performs intrapixel differencing |
766 | ;void (png_row_infop row_info, bytep row) |
766 | ;void (png_row_infop row_info, bytep row) |
767 | align 4 |
767 | align 4 |
768 | proc png_do_write_intrapixel uses eax ebx ecx edx edi, row_info:dword, row:dword |
768 | proc png_do_write_intrapixel uses eax ebx ecx edx edi, row_info:dword, row:dword |
769 | png_debug 1, 'in png_do_write_intrapixel' |
769 | png_debug 1, 'in png_do_write_intrapixel' |
770 | 770 | ||
771 | mov ebx,[row_info] |
771 | mov ebx,[row_info] |
772 | movzx eax,byte[ebx+png_row_info.color_type] |
772 | movzx eax,byte[ebx+png_row_info.color_type] |
773 | and eax,PNG_COLOR_MASK_COLOR |
773 | and eax,PNG_COLOR_MASK_COLOR |
774 | jz .end_f ;if (..!=0) |
774 | jz .end_f ;if (..!=0) |
775 | ;edx = bytes_per_pixel |
775 | ;edx = bytes_per_pixel |
776 | mov ecx,[ebx+png_row_info.width] ;ecx = row_width |
776 | mov ecx,[ebx+png_row_info.width] ;ecx = row_width |
777 | cmp byte[ebx+png_row_info.bit_depth],8 ;if (..==8) |
777 | cmp byte[ebx+png_row_info.bit_depth],8 ;if (..==8) |
778 | jne .end0 |
778 | jne .end0 |
779 | ; bytep rp; |
779 | ; bytep rp; |
780 | ; uint_32 i; |
780 | ; uint_32 i; |
781 | 781 | ||
782 | cmp byte[ebx+png_row_info.color_type],PNG_COLOR_TYPE_RGB |
782 | cmp byte[ebx+png_row_info.color_type],PNG_COLOR_TYPE_RGB |
783 | jne @f ;if (..==..) |
783 | jne @f ;if (..==..) |
784 | mov edx,3-1 ;(-1) for stosb |
784 | mov edx,3-1 ;(-1) for stosb |
785 | jmp .end2 |
785 | jmp .end2 |
786 | @@: |
786 | @@: |
787 | cmp byte[ebx+png_row_info.color_type],PNG_COLOR_TYPE_RGB_ALPHA |
787 | cmp byte[ebx+png_row_info.color_type],PNG_COLOR_TYPE_RGB_ALPHA |
788 | jne @f ;else if (..==..) |
788 | jne @f ;else if (..==..) |
789 | mov edx,4-1 ;(-1) for stosb |
789 | mov edx,4-1 ;(-1) for stosb |
790 | jmp .end2 |
790 | jmp .end2 |
791 | @@: |
791 | @@: |
792 | jmp .end_f ;else return |
792 | jmp .end_f ;else return |
793 | .end2: |
793 | .end2: |
794 | 794 | ||
795 | mov edi,[row] |
795 | mov edi,[row] |
796 | align 4 |
796 | align 4 |
797 | .cycle0: ;for (i = 0, rp = row; i < row_width; i++, rp += bytes_per_pixel) |
797 | .cycle0: ;for (i = 0, rp = row; i < row_width; i++, rp += bytes_per_pixel) |
798 | mov ax,word[edi] |
798 | mov ax,word[edi] |
799 | sub al,ah |
799 | sub al,ah |
800 | stosb ;*(rp) = (byte)(*rp - *(rp + 1)) |
800 | stosb ;*(rp) = (byte)(*rp - *(rp + 1)) |
801 | mov ax,word[edi] |
801 | mov ax,word[edi] |
802 | sub ah,al |
802 | sub ah,al |
803 | mov byte[edi+1],ah ;*(rp + 2) = (byte)(*(rp + 2) - *(rp + 1)) |
803 | mov byte[edi+1],ah ;*(rp + 2) = (byte)(*(rp + 2) - *(rp + 1)) |
804 | add edi,edx |
804 | add edi,edx |
805 | loop .cycle0 |
805 | loop .cycle0 |
806 | .cycle0end: |
806 | .cycle0end: |
807 | jmp .end_f |
807 | jmp .end_f |
808 | .end0: |
808 | .end0: |
809 | 809 | ||
810 | if PNG_WRITE_16BIT_SUPPORTED eq 1 |
810 | if PNG_WRITE_16BIT_SUPPORTED eq 1 |
811 | cmp byte[ebx+png_row_info.bit_depth],16 ;else if (..==16) |
811 | cmp byte[ebx+png_row_info.bit_depth],16 ;else if (..==16) |
812 | jne .end1 |
812 | jne .end1 |
813 | ; bytep rp; |
813 | ; bytep rp; |
814 | ; uint_32 i; |
814 | ; uint_32 i; |
815 | 815 | ||
816 | cmp byte[ebx+png_row_info.color_type],PNG_COLOR_TYPE_RGB |
816 | cmp byte[ebx+png_row_info.color_type],PNG_COLOR_TYPE_RGB |
817 | jne @f ;if (..==..) |
817 | jne @f ;if (..==..) |
818 | mov edx,6 |
818 | mov edx,6 |
819 | jmp .end3 |
819 | jmp .end3 |
820 | @@: |
820 | @@: |
821 | cmp byte[ebx+png_row_info.color_type],PNG_COLOR_TYPE_RGB_ALPHA |
821 | cmp byte[ebx+png_row_info.color_type],PNG_COLOR_TYPE_RGB_ALPHA |
822 | jne @f ;else if (..==..) |
822 | jne @f ;else if (..==..) |
823 | mov edx,8 |
823 | mov edx,8 |
824 | jmp .end3 |
824 | jmp .end3 |
825 | @@: |
825 | @@: |
826 | jmp .end_f ;else return |
826 | jmp .end_f ;else return |
827 | .end3: |
827 | .end3: |
828 | 828 | ||
829 | mov edi,[row] |
829 | mov edi,[row] |
830 | align 4 |
830 | align 4 |
831 | .cycle1: ;for (i = 0, rp = row; i < row_width; i++, rp += bytes_per_pixel) |
831 | .cycle1: ;for (i = 0, rp = row; i < row_width; i++, rp += bytes_per_pixel) |
832 | ; uint_32 s0 = (*(rp ) << 8) | *(rp + 1); |
832 | ; uint_32 s0 = (*(rp ) << 8) | *(rp + 1); |
833 | ; uint_32 s1 = (*(rp + 2) << 8) | *(rp + 3); |
833 | ; uint_32 s1 = (*(rp + 2) << 8) | *(rp + 3); |
834 | ; uint_32 s2 = (*(rp + 4) << 8) | *(rp + 5); |
834 | ; uint_32 s2 = (*(rp + 4) << 8) | *(rp + 5); |
835 | ; uint_32 red = (uint_32)((s0 - s1) & 0xffffL); |
835 | ; uint_32 red = (uint_32)((s0 - s1) & 0xffffL); |
836 | ; uint_32 blue = (uint_32)((s2 - s1) & 0xffffL); |
836 | ; uint_32 blue = (uint_32)((s2 - s1) & 0xffffL); |
837 | ; *(rp ) = (byte)(red >> 8); |
837 | ; *(rp ) = (byte)(red >> 8); |
838 | ; *(rp + 1) = (byte)red; |
838 | ; *(rp + 1) = (byte)red; |
839 | ; *(rp + 4) = (byte)(blue >> 8); |
839 | ; *(rp + 4) = (byte)(blue >> 8); |
840 | ; *(rp + 5) = (byte)blue; |
840 | ; *(rp + 5) = (byte)blue; |
841 | add edi,edx |
841 | add edi,edx |
842 | loop .cycle1 |
842 | loop .cycle1 |
843 | .cycle1end: |
843 | .cycle1end: |
844 | .end1: |
844 | .end1: |
845 | end if ;WRITE_16BIT |
845 | end if ;WRITE_16BIT |
846 | .end_f: |
846 | .end_f: |
847 | ret |
847 | ret |
848 | endp |
848 | endp |
849 | 849 | ||
850 | ; Called by user to write a row of image data |
850 | ; Called by user to write a row of image data |
851 | ;void (png_structrp png_ptr, bytep row) |
851 | ;void (png_structrp png_ptr, bytep row) |
852 | align 4 |
852 | align 4 |
853 | proc png_write_row, png_ptr:dword, row:dword |
853 | proc png_write_row, png_ptr:dword, row:dword |
854 | locals |
854 | locals |
855 | ; 1.5.6: moved from png_struct to be a local structure: |
855 | ; 1.5.6: moved from png_struct to be a local structure: |
856 | row_info png_row_info |
856 | row_info png_row_info |
857 | endl |
857 | endl |
858 | pushad |
858 | pushad |
859 | mov edi,[png_ptr] |
859 | mov edi,[png_ptr] |
860 | cmp edi,0 |
860 | cmp edi,0 |
861 | je .end_f ;if(..==0) return |
861 | je .end_f ;if(..==0) return |
862 | 862 | ||
863 | ; png_debug2(1, "in png_write_row (row %u, pass %d)", |
863 | ; png_debug2(1, "in png_write_row (row %u, pass %d)", |
864 | ; png_ptr->row_number, png_ptr->pass); |
864 | ; png_ptr->row_number, png_ptr->pass); |
865 | png_debug1 1, 'in png_write_row (row %u)',[edi+png_struct.row_number] |
865 | png_debug1 1, 'in png_write_row (row %u)',[edi+png_struct.row_number] |
866 | 866 | ||
867 | ; Initialize transformations and other stuff if first time |
867 | ; Initialize transformations and other stuff if first time |
868 | cmp dword[edi+png_struct.row_number],0 |
868 | cmp dword[edi+png_struct.row_number],0 |
869 | jne .end0 |
869 | jne .end0 |
870 | cmp byte[edi+png_struct.pass],0 |
870 | cmp byte[edi+png_struct.pass],0 |
871 | jne .end0 ;if(..==0 && ..==0) |
871 | jne .end0 ;if(..==0 && ..==0) |
872 | 872 | ||
873 | ; Make sure we wrote the header info |
873 | ; Make sure we wrote the header info |
874 | mov eax,[edi+png_struct.mode] |
874 | mov eax,[edi+png_struct.mode] |
875 | and eax,PNG_WROTE_INFO_BEFORE_PLTE |
875 | and eax,PNG_WROTE_INFO_BEFORE_PLTE |
876 | jnz @f ;if(..==0) |
876 | jnz @f ;if(..==0) |
877 | png_error edi, 'png_write_info was never called before png_write_row' |
877 | png_error edi, 'png_write_info was never called before png_write_row' |
878 | @@: |
878 | @@: |
879 | 879 | ||
880 | ; Check for transforms that have been set but were defined out |
880 | ; Check for transforms that have been set but were defined out |
881 | if (PNG_WRITE_INVERT_SUPPORTED eq 0) & (PNG_READ_INVERT_SUPPORTED eq 1) |
881 | if (PNG_WRITE_INVERT_SUPPORTED eq 0) & (PNG_READ_INVERT_SUPPORTED eq 1) |
882 | mov eax,[edi+png_struct.transformations] |
882 | mov eax,[edi+png_struct.transformations] |
883 | and eax,PNG_INVERT_MONO |
883 | and eax,PNG_INVERT_MONO |
884 | jz @f ;if(..!=0) |
884 | jz @f ;if(..!=0) |
885 | png_warning edi, 'PNG_WRITE_INVERT_SUPPORTED is not defined' |
885 | png_warning edi, 'PNG_WRITE_INVERT_SUPPORTED is not defined' |
886 | @@: |
886 | @@: |
887 | end if |
887 | end if |
888 | 888 | ||
889 | if (PNG_WRITE_FILLER_SUPPORTED eq 0) & (PNG_READ_FILLER_SUPPORTED eq 1) |
889 | if (PNG_WRITE_FILLER_SUPPORTED eq 0) & (PNG_READ_FILLER_SUPPORTED eq 1) |
890 | mov eax,[edi+png_struct.transformations] |
890 | mov eax,[edi+png_struct.transformations] |
891 | and eax,PNG_FILLER |
891 | and eax,PNG_FILLER |
892 | jz @f ;if(..!=0) |
892 | jz @f ;if(..!=0) |
893 | png_warning edi, 'PNG_WRITE_FILLER_SUPPORTED is not defined' |
893 | png_warning edi, 'PNG_WRITE_FILLER_SUPPORTED is not defined' |
894 | @@: |
894 | @@: |
895 | end if |
895 | end if |
896 | 896 | ||
897 | if (PNG_WRITE_PACKSWAP_SUPPORTED eq 0) & (PNG_READ_PACKSWAP_SUPPORTED eq 1) |
897 | if (PNG_WRITE_PACKSWAP_SUPPORTED eq 0) & (PNG_READ_PACKSWAP_SUPPORTED eq 1) |
898 | mov eax,[edi+png_struct.transformations] |
898 | mov eax,[edi+png_struct.transformations] |
899 | and eax,PNG_PACKSWAP |
899 | and eax,PNG_PACKSWAP |
900 | jz @f ;if(..!=0) |
900 | jz @f ;if(..!=0) |
901 | png_warning edi, 'PNG_WRITE_PACKSWAP_SUPPORTED is not defined' |
901 | png_warning edi, 'PNG_WRITE_PACKSWAP_SUPPORTED is not defined' |
902 | @@: |
902 | @@: |
903 | end if |
903 | end if |
904 | 904 | ||
905 | if (PNG_WRITE_PACK_SUPPORTED eq 0) & (PNG_READ_PACK_SUPPORTED eq 1) |
905 | if (PNG_WRITE_PACK_SUPPORTED eq 0) & (PNG_READ_PACK_SUPPORTED eq 1) |
906 | mov eax,[edi+png_struct.transformations] |
906 | mov eax,[edi+png_struct.transformations] |
907 | and eax,PNG_PACK |
907 | and eax,PNG_PACK |
908 | jz @f ;if(..!=0) |
908 | jz @f ;if(..!=0) |
909 | png_warning edi, 'PNG_WRITE_PACK_SUPPORTED is not defined' |
909 | png_warning edi, 'PNG_WRITE_PACK_SUPPORTED is not defined' |
910 | @@: |
910 | @@: |
911 | end if |
911 | end if |
912 | 912 | ||
913 | if (PNG_WRITE_SHIFT_SUPPORTED eq 0) & (PNG_READ_SHIFT_SUPPORTED eq 1) |
913 | if (PNG_WRITE_SHIFT_SUPPORTED eq 0) & (PNG_READ_SHIFT_SUPPORTED eq 1) |
914 | mov eax,[edi+png_struct.transformations] |
914 | mov eax,[edi+png_struct.transformations] |
915 | and eax,PNG_SHIFT |
915 | and eax,PNG_SHIFT |
916 | jz @f ;if(..!=0) |
916 | jz @f ;if(..!=0) |
917 | png_warning edi, 'PNG_WRITE_SHIFT_SUPPORTED is not defined' |
917 | png_warning edi, 'PNG_WRITE_SHIFT_SUPPORTED is not defined' |
918 | @@: |
918 | @@: |
919 | end if |
919 | end if |
920 | 920 | ||
921 | if (PNG_WRITE_BGR_SUPPORTED eq 0) & (PNG_READ_BGR_SUPPORTED eq 1) |
921 | if (PNG_WRITE_BGR_SUPPORTED eq 0) & (PNG_READ_BGR_SUPPORTED eq 1) |
922 | mov eax,[edi+png_struct.transformations] |
922 | mov eax,[edi+png_struct.transformations] |
923 | and eax,PNG_BGR |
923 | and eax,PNG_BGR |
924 | jz @f ;if(..!=0) |
924 | jz @f ;if(..!=0) |
925 | png_warning edi, 'PNG_WRITE_BGR_SUPPORTED is not defined' |
925 | png_warning edi, 'PNG_WRITE_BGR_SUPPORTED is not defined' |
926 | @@: |
926 | @@: |
927 | end if |
927 | end if |
928 | 928 | ||
929 | if (PNG_WRITE_SWAP_SUPPORTED eq 0) & (PNG_READ_SWAP_SUPPORTED eq 1) |
929 | if (PNG_WRITE_SWAP_SUPPORTED eq 0) & (PNG_READ_SWAP_SUPPORTED eq 1) |
930 | mov eax,[edi+png_struct.transformations] |
930 | mov eax,[edi+png_struct.transformations] |
931 | and eax,PNG_SWAP_BYTES |
931 | and eax,PNG_SWAP_BYTES |
932 | jz @f ;if(..!=0) |
932 | jz @f ;if(..!=0) |
933 | png_warning edi, 'PNG_WRITE_SWAP_SUPPORTED is not defined' |
933 | png_warning edi, 'PNG_WRITE_SWAP_SUPPORTED is not defined' |
934 | @@: |
934 | @@: |
935 | end if |
935 | end if |
936 | 936 | ||
937 | stdcall png_write_start_row, edi |
937 | stdcall png_write_start_row, edi |
938 | .end0: |
938 | .end0: |
939 | 939 | ||
940 | if PNG_WRITE_INTERLACING_SUPPORTED eq 1 |
940 | if PNG_WRITE_INTERLACING_SUPPORTED eq 1 |
941 | ; If interlaced and not interested in row, return |
941 | ; If interlaced and not interested in row, return |
942 | cmp byte[edi+png_struct.interlaced],0 |
942 | cmp byte[edi+png_struct.interlaced],0 |
943 | je .end1 |
943 | je .end1 |
944 | mov eax,[edi+png_struct.transformations] |
944 | mov eax,[edi+png_struct.transformations] |
945 | and eax,PNG_INTERLACE |
945 | and eax,PNG_INTERLACE |
946 | jz .end1 ;if(..!=0 && ..!=0) |
946 | jz .end1 ;if(..!=0 && ..!=0) |
947 | cmp byte[edi+png_struct.pass],0 |
947 | cmp byte[edi+png_struct.pass],0 |
948 | jne @f |
948 | jne @f |
949 | mov eax,[edi+png_struct.row_number] |
949 | mov eax,[edi+png_struct.row_number] |
950 | and eax,0x07 |
950 | and eax,0x07 |
951 | jz .end1 ;if (..!=0) |
951 | jz .end1 ;if (..!=0) |
952 | stdcall png_write_finish_row, edi |
952 | stdcall png_write_finish_row, edi |
953 | jmp .end_f |
953 | jmp .end_f |
954 | @@: |
954 | @@: |
955 | cmp byte[edi+png_struct.pass],1 |
955 | cmp byte[edi+png_struct.pass],1 |
956 | jne @f |
956 | jne @f |
957 | mov eax,[edi+png_struct.row_number] |
957 | mov eax,[edi+png_struct.row_number] |
958 | and eax,0x07 |
958 | and eax,0x07 |
959 | jnz .end2 |
959 | jnz .end2 |
960 | cmp dword[edi+png_struct.width],5 |
960 | cmp dword[edi+png_struct.width],5 |
961 | jge .end1 ;if (..!=0 || ..<..) |
961 | jge .end1 ;if (..!=0 || ..<..) |
962 | .end2: |
962 | .end2: |
963 | stdcall png_write_finish_row, edi |
963 | stdcall png_write_finish_row, edi |
964 | jmp .end_f |
964 | jmp .end_f |
965 | @@: |
965 | @@: |
966 | cmp byte[edi+png_struct.pass],2 |
966 | cmp byte[edi+png_struct.pass],2 |
967 | jne @f |
967 | jne @f |
968 | mov eax,[edi+png_struct.row_number] |
968 | mov eax,[edi+png_struct.row_number] |
969 | and eax,0x07 |
969 | and eax,0x07 |
970 | cmp eax,4 |
970 | cmp eax,4 |
971 | je .end1 ;if (..!=..) |
971 | je .end1 ;if (..!=..) |
972 | stdcall png_write_finish_row, edi |
972 | stdcall png_write_finish_row, edi |
973 | jmp .end_f |
973 | jmp .end_f |
974 | @@: |
974 | @@: |
975 | cmp byte[edi+png_struct.pass],3 |
975 | cmp byte[edi+png_struct.pass],3 |
976 | jne @f |
976 | jne @f |
977 | mov eax,[edi+png_struct.row_number] |
977 | mov eax,[edi+png_struct.row_number] |
978 | and eax,0x03 |
978 | and eax,0x03 |
979 | jnz .end3 |
979 | jnz .end3 |
980 | cmp dword[edi+png_struct.width],3 |
980 | cmp dword[edi+png_struct.width],3 |
981 | jge .end1 ;if (..!=0 || ..<..) |
981 | jge .end1 ;if (..!=0 || ..<..) |
982 | .end3: |
982 | .end3: |
983 | stdcall png_write_finish_row, edi |
983 | stdcall png_write_finish_row, edi |
984 | jmp .end_f |
984 | jmp .end_f |
985 | @@: |
985 | @@: |
986 | cmp byte[edi+png_struct.pass],4 |
986 | cmp byte[edi+png_struct.pass],4 |
987 | jne @f |
987 | jne @f |
988 | mov eax,[edi+png_struct.row_number] |
988 | mov eax,[edi+png_struct.row_number] |
989 | and eax,0x03 |
989 | and eax,0x03 |
990 | cmp eax,2 |
990 | cmp eax,2 |
991 | je .end1 ;if (..!=..) |
991 | je .end1 ;if (..!=..) |
992 | stdcall png_write_finish_row, edi |
992 | stdcall png_write_finish_row, edi |
993 | jmp .end_f |
993 | jmp .end_f |
994 | @@: |
994 | @@: |
995 | cmp byte[edi+png_struct.pass],5 |
995 | cmp byte[edi+png_struct.pass],5 |
996 | jne @f |
996 | jne @f |
997 | mov eax,[edi+png_struct.row_number] |
997 | mov eax,[edi+png_struct.row_number] |
998 | and eax,0x01 |
998 | and eax,0x01 |
999 | jnz .end4 |
999 | jnz .end4 |
1000 | cmp dword[edi+png_struct.width],2 |
1000 | cmp dword[edi+png_struct.width],2 |
1001 | jge .end1 ;if (..!=0 || ..<..) |
1001 | jge .end1 ;if (..!=0 || ..<..) |
1002 | .end4: |
1002 | .end4: |
1003 | stdcall png_write_finish_row, edi |
1003 | stdcall png_write_finish_row, edi |
1004 | jmp .end_f |
1004 | jmp .end_f |
1005 | @@: |
1005 | @@: |
1006 | cmp byte[edi+png_struct.pass],6 |
1006 | cmp byte[edi+png_struct.pass],6 |
1007 | jne .end1 |
1007 | jne .end1 |
1008 | mov eax,[edi+png_struct.row_number] |
1008 | mov eax,[edi+png_struct.row_number] |
1009 | and eax,0x01 |
1009 | and eax,0x01 |
1010 | jnz .end1 ;if (..==0) |
1010 | jnz .end1 ;if (..==0) |
1011 | stdcall png_write_finish_row, edi |
1011 | stdcall png_write_finish_row, edi |
1012 | jmp .end_f |
1012 | jmp .end_f |
1013 | .end1: |
1013 | .end1: |
1014 | end if |
1014 | end if |
1015 | 1015 | ||
1016 | ; Set up row info for transformations |
1016 | ; Set up row info for transformations |
1017 | mov ebx,ebp |
1017 | mov ebx,ebp |
1018 | sub ebx,sizeof.png_row_info |
1018 | sub ebx,sizeof.png_row_info |
1019 | mov al,byte[edi+png_struct.color_type] |
1019 | mov al,byte[edi+png_struct.color_type] |
1020 | mov byte[ebx+png_row_info.color_type],al |
1020 | mov byte[ebx+png_row_info.color_type],al |
1021 | mov eax,[edi+png_struct.usr_width] |
1021 | mov eax,[edi+png_struct.usr_width] |
1022 | mov [ebx+png_row_info.width],eax |
1022 | mov [ebx+png_row_info.width],eax |
1023 | movzx eax,byte[edi+png_struct.usr_channels] |
1023 | movzx eax,byte[edi+png_struct.usr_channels] |
1024 | mov byte[ebx+png_row_info.channels],al |
1024 | mov byte[ebx+png_row_info.channels],al |
1025 | movzx ecx,byte[edi+png_struct.usr_bit_depth] |
1025 | movzx ecx,byte[edi+png_struct.usr_bit_depth] |
1026 | mov byte[ebx+png_row_info.bit_depth],cl |
1026 | mov byte[ebx+png_row_info.bit_depth],cl |
1027 | imul eax,ecx ;.bit_depth * .channels |
1027 | imul eax,ecx ;.bit_depth * .channels |
1028 | mov byte[ebx+png_row_info.pixel_depth],al |
1028 | mov byte[ebx+png_row_info.pixel_depth],al |
1029 | PNG_ROWBYTES eax, [ebx+png_row_info.width] |
1029 | PNG_ROWBYTES eax, [ebx+png_row_info.width] |
1030 | mov [ebx+png_row_info.rowbytes], eax |
1030 | mov [ebx+png_row_info.rowbytes], eax |
1031 | 1031 | ||
1032 | push eax |
1032 | push eax |
1033 | movzx eax,byte[ebx+png_row_info.color_type] |
1033 | movzx eax,byte[ebx+png_row_info.color_type] |
1034 | png_debug1 3, 'row_info->color_type = %d', eax |
1034 | png_debug1 3, 'row_info->color_type = %d', eax |
1035 | png_debug1 3, 'row_info->width = %u', [ebx+png_row_info.width] |
1035 | png_debug1 3, 'row_info->width = %u', [ebx+png_row_info.width] |
1036 | movzx eax,byte[ebx+png_row_info.channels] |
1036 | movzx eax,byte[ebx+png_row_info.channels] |
1037 | png_debug1 3, 'row_info->channels = %d', eax |
1037 | png_debug1 3, 'row_info->channels = %d', eax |
1038 | movzx eax,byte[ebx+png_row_info.bit_depth] |
1038 | movzx eax,byte[ebx+png_row_info.bit_depth] |
1039 | png_debug1 3, 'row_info->bit_depth = %d', eax |
1039 | png_debug1 3, 'row_info->bit_depth = %d', eax |
1040 | movzx eax,byte[ebx+png_row_info.pixel_depth] |
1040 | movzx eax,byte[ebx+png_row_info.pixel_depth] |
1041 | png_debug1 3, 'row_info->pixel_depth = %d', eax |
1041 | png_debug1 3, 'row_info->pixel_depth = %d', eax |
1042 | png_debug1 3, 'row_info->rowbytes = %lu', [ebx+png_row_info.rowbytes] |
1042 | png_debug1 3, 'row_info->rowbytes = %lu', [ebx+png_row_info.rowbytes] |
1043 | pop eax |
1043 | pop eax |
1044 | 1044 | ||
1045 | ; Copy user's row into buffer, leaving room for filter byte. |
1045 | ; Copy user's row into buffer, leaving room for filter byte. |
1046 | push edi |
1046 | push edi |
1047 | mov edi,[edi+png_struct.row_buf] |
1047 | mov edi,[edi+png_struct.row_buf] |
1048 | inc edi |
1048 | inc edi |
1049 | mov esi,[row] |
1049 | mov esi,[row] |
1050 | mov ecx,eax |
1050 | mov ecx,eax |
1051 | rep movsb ;memcpy(... |
1051 | rep movsb ;memcpy(... |
1052 | pop edi |
1052 | pop edi |
1053 | 1053 | ||
1054 | if PNG_WRITE_INTERLACING_SUPPORTED eq 1 |
1054 | if PNG_WRITE_INTERLACING_SUPPORTED eq 1 |
1055 | ; Handle interlacing |
1055 | ; Handle interlacing |
1056 | cmp byte[edi+png_struct.interlaced],0 |
1056 | cmp byte[edi+png_struct.interlaced],0 |
1057 | je @f |
1057 | je @f |
1058 | cmp byte[edi+png_struct.pass],6 |
1058 | cmp byte[edi+png_struct.pass],6 |
1059 | jge @f |
1059 | jge @f |
1060 | mov eax,[edi+png_struct.transformations] |
1060 | mov eax,[edi+png_struct.transformations] |
1061 | and eax,PNG_INTERLACE |
1061 | and eax,PNG_INTERLACE |
1062 | jz @f ;if (.. && ..<.. && ..!=0) |
1062 | jz @f ;if (.. && ..<.. && ..!=0) |
1063 | movzx eax,byte[edi+png_struct.pass] |
1063 | movzx eax,byte[edi+png_struct.pass] |
1064 | push eax |
1064 | push eax |
1065 | mov eax,[edi+png_struct.row_buf] |
1065 | mov eax,[edi+png_struct.row_buf] |
1066 | inc eax |
1066 | inc eax |
1067 | stdcall png_do_write_interlace, ebx, eax ;, ...pass |
1067 | stdcall png_do_write_interlace, ebx, eax ;, ...pass |
1068 | ; This should always get caught above, but still ... |
1068 | ; This should always get caught above, but still ... |
1069 | cmp dword[ebx+png_row_info.width],0 |
1069 | cmp dword[ebx+png_row_info.width],0 |
1070 | jne @f ;if (..==0) |
1070 | jne @f ;if (..==0) |
1071 | stdcall png_write_finish_row, edi |
1071 | stdcall png_write_finish_row, edi |
1072 | jmp .end_f |
1072 | jmp .end_f |
1073 | @@: |
1073 | @@: |
1074 | end if |
1074 | end if |
1075 | 1075 | ||
1076 | if PNG_WRITE_TRANSFORMS_SUPPORTED eq 1 |
1076 | if PNG_WRITE_TRANSFORMS_SUPPORTED eq 1 |
1077 | ; Handle other transformations |
1077 | ; Handle other transformations |
1078 | cmp dword[edi+png_struct.transformations],0 |
1078 | cmp dword[edi+png_struct.transformations],0 |
1079 | je @f ;if (..!=0) |
1079 | je @f ;if (..!=0) |
1080 | stdcall png_do_write_transformations, edi, ebx |
1080 | stdcall png_do_write_transformations, edi, ebx |
1081 | @@: |
1081 | @@: |
1082 | end if |
1082 | end if |
1083 | 1083 | ||
1084 | ; At this point the row_info pixel depth must match the 'transformed' depth, |
1084 | ; At this point the row_info pixel depth must match the 'transformed' depth, |
1085 | ; which is also the output depth. |
1085 | ; which is also the output depth. |
1086 | 1086 | ||
1087 | mov al,[ebx+png_row_info.pixel_depth] |
1087 | mov al,[ebx+png_row_info.pixel_depth] |
1088 | cmp al,[edi+png_struct.pixel_depth] |
1088 | cmp al,[edi+png_struct.pixel_depth] |
1089 | jne @f |
1089 | jne @f |
1090 | cmp al,[edi+png_struct.transformed_pixel_depth] |
1090 | cmp al,[edi+png_struct.transformed_pixel_depth] |
1091 | je .end5 |
1091 | je .end5 |
1092 | @@: ;if (..!=.. || ..!=..) |
1092 | @@: ;if (..!=.. || ..!=..) |
1093 | png_error edi, 'internal write transform logic error' |
1093 | png_error edi, 'internal write transform logic error' |
1094 | .end5: |
1094 | .end5: |
1095 | 1095 | ||
1096 | if PNG_MNG_FEATURES_SUPPORTED eq 1 |
1096 | if PNG_MNG_FEATURES_SUPPORTED eq 1 |
1097 | ; Write filter_method 64 (intrapixel differencing) only if |
1097 | ; Write filter_method 64 (intrapixel differencing) only if |
1098 | ; 1. Libpng was compiled with PNG_MNG_FEATURES_SUPPORTED and |
1098 | ; 1. Libpng was compiled with PNG_MNG_FEATURES_SUPPORTED and |
1099 | ; 2. Libpng did not write a PNG signature (this filter_method is only |
1099 | ; 2. Libpng did not write a PNG signature (this filter_method is only |
1100 | ; used in PNG datastreams that are embedded in MNG datastreams) and |
1100 | ; used in PNG datastreams that are embedded in MNG datastreams) and |
1101 | ; 3. The application called png_permit_mng_features with a mask that |
1101 | ; 3. The application called png_permit_mng_features with a mask that |
1102 | ; included PNG_FLAG_MNG_FILTER_64 and |
1102 | ; included PNG_FLAG_MNG_FILTER_64 and |
1103 | ; 4. The filter_method is 64 and |
1103 | ; 4. The filter_method is 64 and |
1104 | ; 5. The color_type is RGB or RGBA |
1104 | ; 5. The color_type is RGB or RGBA |
1105 | 1105 | ||
1106 | mov eax,[edi+png_struct.mng_features_permitted] |
1106 | mov eax,[edi+png_struct.mng_features_permitted] |
1107 | and eax,PNG_FLAG_MNG_FILTER_64 |
1107 | and eax,PNG_FLAG_MNG_FILTER_64 |
1108 | jz @f |
1108 | jz @f |
1109 | cmp byte[edi+png_struct.filter_type],PNG_INTRAPIXEL_DIFFERENCING |
1109 | cmp byte[edi+png_struct.filter_type],PNG_INTRAPIXEL_DIFFERENCING |
1110 | jne @f ;if (..!=0 && ..==..) |
1110 | jne @f ;if (..!=0 && ..==..) |
1111 | ; Intrapixel differencing |
1111 | ; Intrapixel differencing |
1112 | mov eax,[edi+png_struct.row_buf] |
1112 | mov eax,[edi+png_struct.row_buf] |
1113 | inc eax |
1113 | inc eax |
1114 | stdcall png_do_write_intrapixel, ebx, eax |
1114 | stdcall png_do_write_intrapixel, ebx, eax |
1115 | @@: |
1115 | @@: |
1116 | end if |
1116 | end if |
1117 | 1117 | ||
1118 | ; Added at libpng-1.5.10 |
1118 | ; Added at libpng-1.5.10 |
1119 | if PNG_WRITE_CHECK_FOR_INVALID_INDEX_SUPPORTED eq 1 |
1119 | if PNG_WRITE_CHECK_FOR_INVALID_INDEX_SUPPORTED eq 1 |
1120 | ; Check for out-of-range palette index |
1120 | ; Check for out-of-range palette index |
1121 | cmp byte[ebx+png_row_info.color_type],PNG_COLOR_TYPE_PALETTE |
1121 | cmp byte[ebx+png_row_info.color_type],PNG_COLOR_TYPE_PALETTE |
1122 | jne @f |
1122 | jne @f |
1123 | cmp dword[edi+png_struct.num_palette_max],0 |
1123 | cmp dword[edi+png_struct.num_palette_max],0 |
1124 | jl @f ;if (..==.. && ..>=0) |
1124 | jl @f ;if (..==.. && ..>=0) |
1125 | stdcall png_do_check_palette_indexes, edi, ebx |
1125 | stdcall png_do_check_palette_indexes, edi, ebx |
1126 | @@: |
1126 | @@: |
1127 | end if |
1127 | end if |
1128 | 1128 | ||
1129 | ; Find a filter if necessary, filter the row and write it out. |
1129 | ; Find a filter if necessary, filter the row and write it out. |
1130 | mov ebx,ebp |
1130 | mov ebx,ebp |
1131 | sub ebx,sizeof.png_row_info |
1131 | sub ebx,sizeof.png_row_info |
1132 | stdcall png_write_find_filter, edi, ebx |
1132 | stdcall png_write_find_filter, edi, ebx |
1133 | 1133 | ||
1134 | cmp dword[edi+png_struct.write_row_fn],0 |
1134 | cmp dword[edi+png_struct.write_row_fn],0 |
1135 | je .end_f ;if (..!=0) |
1135 | je .end_f ;if (..!=0) |
1136 | movzx eax,byte[edi+png_struct.pass] |
1136 | movzx eax,byte[edi+png_struct.pass] |
1137 | stdcall dword[edi+png_struct.write_row_fn], edi, [edi+png_struct.row_number], eax |
1137 | stdcall dword[edi+png_struct.write_row_fn], edi, [edi+png_struct.row_number], eax |
1138 | .end_f: |
1138 | .end_f: |
1139 | popad |
1139 | popad |
1140 | ret |
1140 | ret |
1141 | endp |
1141 | endp |
1142 | 1142 | ||
1143 | ; Set the automatic flush interval or 0 to turn flushing off |
1143 | ; Set the automatic flush interval or 0 to turn flushing off |
1144 | ;void (png_structrp png_ptr, int nrows) |
1144 | ;void (png_structrp png_ptr, int nrows) |
1145 | align 4 |
1145 | align 4 |
1146 | proc png_set_flush uses eax edi, png_ptr:dword, nrows:dword |
1146 | proc png_set_flush uses eax edi, png_ptr:dword, nrows:dword |
1147 | png_debug 1, 'in png_set_flush' |
1147 | png_debug 1, 'in png_set_flush' |
1148 | 1148 | ||
1149 | mov edi,[png_ptr] |
1149 | mov edi,[png_ptr] |
1150 | cmp edi,0 |
1150 | cmp edi,0 |
1151 | je .end_f ;if (..==0) return |
1151 | je .end_f ;if (..==0) return |
1152 | 1152 | ||
1153 | mov eax,[nrows] |
1153 | mov eax,[nrows] |
1154 | cmp eax,0 |
1154 | cmp eax,0 |
1155 | jge @f ;(nrows < 0 ? 0 : nrows) |
1155 | jge @f ;(nrows < 0 ? 0 : nrows) |
1156 | xor eax,eax |
1156 | xor eax,eax |
1157 | @@: |
1157 | @@: |
1158 | mov [edi+png_struct.flush_dist],eax |
1158 | mov [edi+png_struct.flush_dist],eax |
1159 | .end_f: |
1159 | .end_f: |
1160 | ret |
1160 | ret |
1161 | endp |
1161 | endp |
1162 | 1162 | ||
1163 | ; Flush the current output buffers now |
1163 | ; Flush the current output buffers now |
1164 | ;void (png_structrp png_ptr) |
1164 | ;void (png_structrp png_ptr) |
1165 | align 4 |
1165 | align 4 |
1166 | proc png_write_flush uses eax edi, png_ptr:dword |
1166 | proc png_write_flush uses eax edi, png_ptr:dword |
1167 | png_debug 1, 'in png_write_flush' |
1167 | png_debug 1, 'in png_write_flush' |
1168 | 1168 | ||
1169 | mov edi,[png_ptr] |
1169 | mov edi,[png_ptr] |
1170 | cmp edi,0 |
1170 | cmp edi,0 |
1171 | je .end_f ;if (..==0) return |
1171 | je .end_f ;if (..==0) return |
1172 | 1172 | ||
1173 | ; We have already written out all of the data |
1173 | ; We have already written out all of the data |
1174 | mov eax,[edi+png_struct.num_rows] |
1174 | mov eax,[edi+png_struct.num_rows] |
1175 | cmp [edi+png_struct.row_number],eax |
1175 | cmp [edi+png_struct.row_number],eax |
1176 | jge .end_f ;if (..>=..) return |
1176 | jge .end_f ;if (..>=..) return |
1177 | 1177 | ||
1178 | stdcall png_compress_IDAT, 0, 0, Z_SYNC_FLUSH |
1178 | stdcall png_compress_IDAT, 0, 0, Z_SYNC_FLUSH |
1179 | mov dword[edi+png_struct.flush_rows],0 |
1179 | mov dword[edi+png_struct.flush_rows],0 |
1180 | stdcall png_flush, edi |
1180 | stdcall png_flush, edi |
1181 | .end_f: |
1181 | .end_f: |
1182 | popad |
1182 | popad |
1183 | ret |
1183 | ret |
1184 | endp |
1184 | endp |
1185 | 1185 | ||
1186 | ; Free any memory used in png_ptr struct without freeing the struct itself. |
1186 | ; Free any memory used in png_ptr struct without freeing the struct itself. |
1187 | ;void (png_structrp png_ptr) |
1187 | ;void (png_structrp png_ptr) |
1188 | align 4 |
1188 | align 4 |
1189 | proc png_write_destroy uses eax edi, png_ptr:dword |
1189 | proc png_write_destroy uses eax edi, png_ptr:dword |
1190 | png_debug 1, 'in png_write_destroy' |
1190 | png_debug 1, 'in png_write_destroy' |
1191 | 1191 | ||
1192 | ; Free any memory zlib uses |
1192 | ; Free any memory zlib uses |
1193 | mov edi,[png_ptr] |
1193 | mov edi,[png_ptr] |
1194 | mov eax,[edi+png_struct.flags] |
1194 | mov eax,[edi+png_struct.flags] |
1195 | and eax,PNG_FLAG_ZSTREAM_INITIALIZED |
1195 | and eax,PNG_FLAG_ZSTREAM_INITIALIZED |
1196 | jz @f ;if (..!=0) |
1196 | jz @f ;if (..!=0) |
1197 | mov eax,edi |
1197 | mov eax,edi |
1198 | add eax,png_struct.zstream |
1198 | add eax,png_struct.zstream |
1199 | stdcall [deflateEnd], eax |
1199 | stdcall [deflateEnd], eax |
1200 | @@: |
1200 | @@: |
1201 | 1201 | ||
1202 | ; Free our memory. png_free checks NULL for us. |
1202 | ; Free our memory. png_free checks NULL for us. |
1203 | mov eax,edi |
1203 | mov eax,edi |
1204 | add eax,png_struct.zbuffer_list |
1204 | add eax,png_struct.zbuffer_list |
1205 | stdcall png_free_buffer_list, edi, eax |
1205 | stdcall png_free_buffer_list, edi, eax |
1206 | stdcall png_free, edi, [edi+png_struct.row_buf] |
1206 | stdcall png_free, edi, [edi+png_struct.row_buf] |
1207 | mov dword[edi+png_struct.row_buf],0 |
1207 | mov dword[edi+png_struct.row_buf],0 |
1208 | if PNG_WRITE_FILTER_SUPPORTED eq 1 |
1208 | if PNG_WRITE_FILTER_SUPPORTED eq 1 |
1209 | stdcall png_free, edi, [edi+png_struct.prev_row] |
1209 | stdcall png_free, edi, [edi+png_struct.prev_row] |
1210 | stdcall png_free, edi, [edi+png_struct.try_row] |
1210 | stdcall png_free, edi, [edi+png_struct.try_row] |
1211 | stdcall png_free, edi, [edi+png_struct.tst_row] |
1211 | stdcall png_free, edi, [edi+png_struct.tst_row] |
1212 | mov dword[edi+png_struct.prev_row],0 |
1212 | mov dword[edi+png_struct.prev_row],0 |
1213 | mov dword[edi+png_struct.try_row],0 |
1213 | mov dword[edi+png_struct.try_row],0 |
1214 | mov dword[edi+png_struct.tst_row],0 |
1214 | mov dword[edi+png_struct.tst_row],0 |
1215 | end if |
1215 | end if |
1216 | 1216 | ||
1217 | if PNG_SET_UNKNOWN_CHUNKS_SUPPORTED eq 1 |
1217 | if PNG_SET_UNKNOWN_CHUNKS_SUPPORTED eq 1 |
1218 | stdcall png_free, edi, [edi+png_struct.chunk_list] |
1218 | stdcall png_free, edi, [edi+png_struct.chunk_list] |
1219 | mov dword[edi+png_struct.chunk_list],0 |
1219 | mov dword[edi+png_struct.chunk_list],0 |
1220 | end if |
1220 | end if |
1221 | 1221 | ||
1222 | ; The error handling and memory handling information is left intact at this |
1222 | ; The error handling and memory handling information is left intact at this |
1223 | ; point: the jmp_buf may still have to be freed. See png_destroy_png_struct |
1223 | ; point: the jmp_buf may still have to be freed. See png_destroy_png_struct |
1224 | ; for how this happens. |
1224 | ; for how this happens. |
1225 | ret |
1225 | ret |
1226 | endp |
1226 | endp |
1227 | 1227 | ||
1228 | ; Free all memory used by the write. |
1228 | ; Free all memory used by the write. |
1229 | ; In libpng 1.6.0 this API changed quietly to no longer accept a NULL value for |
1229 | ; In libpng 1.6.0 this API changed quietly to no longer accept a NULL value for |
1230 | ; *png_ptr_ptr. Prior to 1.6.0 it would accept such a value and it would free |
1230 | ; *png_ptr_ptr. Prior to 1.6.0 it would accept such a value and it would free |
1231 | ; the passed in info_structs but it would quietly fail to free any of the data |
1231 | ; the passed in info_structs but it would quietly fail to free any of the data |
1232 | ; inside them. In 1.6.0 it quietly does nothing (it has to be quiet because it |
1232 | ; inside them. In 1.6.0 it quietly does nothing (it has to be quiet because it |
1233 | ; has no png_ptr.) |
1233 | ; has no png_ptr.) |
1234 | 1234 | ||
1235 | ;void (png_structpp png_ptr_ptr, png_infopp info_ptr_ptr) |
1235 | ;void (png_structpp png_ptr_ptr, png_infopp info_ptr_ptr) |
1236 | align 4 |
1236 | align 4 |
1237 | proc png_destroy_write_struct uses edi esi, png_ptr_ptr:dword, info_ptr_ptr:dword |
1237 | proc png_destroy_write_struct uses edi esi, png_ptr_ptr:dword, info_ptr_ptr:dword |
1238 | png_debug 1, 'in png_destroy_write_struct' |
1238 | png_debug 1, 'in png_destroy_write_struct' |
1239 | 1239 | ||
1240 | mov esi,[png_ptr_ptr] |
1240 | mov esi,[png_ptr_ptr] |
1241 | cmp esi,0 |
1241 | cmp esi,0 |
1242 | je @f ;if (..!=0) |
1242 | je @f ;if (..!=0) |
1243 | mov edi,[esi] |
1243 | mov edi,[esi] |
1244 | 1244 | ||
1245 | cmp edi,0 |
1245 | cmp edi,0 |
1246 | je @f ;if (..!=0) ;added in libpng 1.6.0 |
1246 | je @f ;if (..!=0) ;added in libpng 1.6.0 |
1247 | stdcall png_destroy_info_struct, edi, [info_ptr_ptr] |
1247 | stdcall png_destroy_info_struct, edi, [info_ptr_ptr] |
1248 | 1248 | ||
1249 | mov dword[esi],0 |
1249 | mov dword[esi],0 |
1250 | stdcall png_write_destroy, edi |
1250 | stdcall png_write_destroy, edi |
1251 | stdcall png_destroy_png_struct, edi |
1251 | stdcall png_destroy_png_struct, edi |
1252 | @@: |
1252 | @@: |
1253 | ret |
1253 | ret |
1254 | endp |
1254 | endp |
1255 | 1255 | ||
1256 | ; Allow the application to select one or more row filters to use. |
1256 | ; Allow the application to select one or more row filters to use. |
1257 | ;void (png_structrp png_ptr, int method, int filters) |
1257 | ;void (png_structrp png_ptr, int method, int filters) |
1258 | align 4 |
1258 | align 4 |
1259 | proc png_set_filter uses eax ebx ecx edi, png_ptr:dword, method:dword, filters:dword |
1259 | proc png_set_filter uses eax ebx ecx edi, png_ptr:dword, method:dword, filters:dword |
1260 | png_debug 1, 'in png_set_filter' |
1260 | png_debug 1, 'in png_set_filter' |
1261 | pushad |
1261 | pushad |
1262 | mov edi,[png_ptr] |
1262 | mov edi,[png_ptr] |
1263 | cmp edi,0 |
1263 | cmp edi,0 |
1264 | je .end_f ;if (..==0) return |
1264 | je .end_f ;if (..==0) return |
1265 | 1265 | ||
1266 | if PNG_MNG_FEATURES_SUPPORTED eq 1 |
1266 | if PNG_MNG_FEATURES_SUPPORTED eq 1 |
1267 | mov eax,[edi+png_struct.mng_features_permitted] |
1267 | mov eax,[edi+png_struct.mng_features_permitted] |
1268 | and eax,PNG_FLAG_MNG_FILTER_64 |
1268 | and eax,PNG_FLAG_MNG_FILTER_64 |
1269 | je @f |
1269 | je @f |
1270 | cmp dword[method], PNG_INTRAPIXEL_DIFFERENCING |
1270 | cmp dword[method], PNG_INTRAPIXEL_DIFFERENCING |
1271 | jne @f ;if (..!=0 && ..==..) |
1271 | jne @f ;if (..!=0 && ..==..) |
1272 | mov dword[method], PNG_FILTER_TYPE_BASE |
1272 | mov dword[method], PNG_FILTER_TYPE_BASE |
1273 | @@: |
1273 | @@: |
1274 | end if |
1274 | end if |
1275 | cmp dword[method], PNG_FILTER_TYPE_BASE |
1275 | cmp dword[method], PNG_FILTER_TYPE_BASE |
1276 | jne .end0 ;if (..==..) |
1276 | jne .end0 ;if (..==..) |
1277 | mov ebx,[filters] |
1277 | mov ebx,[filters] |
1278 | and ebx,PNG_ALL_FILTERS or 0x07 ;switch (..) |
1278 | and ebx,PNG_ALL_FILTERS or 0x07 ;switch (..) |
1279 | 1279 | ||
1280 | if PNG_WRITE_FILTER_SUPPORTED eq 1 |
1280 | if PNG_WRITE_FILTER_SUPPORTED eq 1 |
1281 | cmp ebx,5 |
1281 | cmp ebx,5 |
1282 | je .end2 |
1282 | je .end2 |
1283 | cmp ebx,6 |
1283 | cmp ebx,6 |
1284 | je .end2 |
1284 | je .end2 |
1285 | cmp ebx,7 |
1285 | cmp ebx,7 |
1286 | je .end2 |
1286 | je .end2 |
1287 | jmp @f |
1287 | jmp @f |
1288 | .end2: |
1288 | .end2: |
1289 | cStr ,'Unknown row filter for method 0' |
1289 | cStr ,'Unknown row filter for method 0' |
1290 | stdcall png_app_error, edi, eax |
1290 | stdcall png_app_error, edi, eax |
1291 | ; FALL THROUGH |
1291 | ; FALL THROUGH |
1292 | @@: |
1292 | @@: |
1293 | end if ;WRITE_FILTER |
1293 | end if ;WRITE_FILTER |
1294 | cmp ebx,PNG_FILTER_VALUE_NONE |
1294 | cmp ebx,PNG_FILTER_VALUE_NONE |
1295 | jne @f |
1295 | jne @f |
1296 | mov byte[edi+png_struct.do_filter],PNG_FILTER_NONE |
1296 | mov byte[edi+png_struct.do_filter],PNG_FILTER_NONE |
1297 | jmp .end1 |
1297 | jmp .end1 |
1298 | @@: |
1298 | @@: |
1299 | if PNG_WRITE_FILTER_SUPPORTED eq 1 |
1299 | if PNG_WRITE_FILTER_SUPPORTED eq 1 |
1300 | cmp ebx,PNG_FILTER_VALUE_SUB |
1300 | cmp ebx,PNG_FILTER_VALUE_SUB |
1301 | jne @f |
1301 | jne @f |
1302 | mov byte[edi+png_struct.do_filter],PNG_FILTER_SUB |
1302 | mov byte[edi+png_struct.do_filter],PNG_FILTER_SUB |
1303 | jmp .end1 |
1303 | jmp .end1 |
1304 | @@: |
1304 | @@: |
1305 | cmp ebx,PNG_FILTER_VALUE_UP |
1305 | cmp ebx,PNG_FILTER_VALUE_UP |
1306 | jne @f |
1306 | jne @f |
1307 | mov byte[edi+png_struct.do_filter],PNG_FILTER_UP |
1307 | mov byte[edi+png_struct.do_filter],PNG_FILTER_UP |
1308 | jmp .end1 |
1308 | jmp .end1 |
1309 | @@: |
1309 | @@: |
1310 | cmp ebx,PNG_FILTER_VALUE_AVG |
1310 | cmp ebx,PNG_FILTER_VALUE_AVG |
1311 | jne @f |
1311 | jne @f |
1312 | mov byte[edi+png_struct.do_filter],PNG_FILTER_AVG |
1312 | mov byte[edi+png_struct.do_filter],PNG_FILTER_AVG |
1313 | jmp .end1 |
1313 | jmp .end1 |
1314 | @@: |
1314 | @@: |
1315 | cmp ebx,PNG_FILTER_VALUE_PAETH |
1315 | cmp ebx,PNG_FILTER_VALUE_PAETH |
1316 | jne @f |
1316 | jne @f |
1317 | mov byte[edi+png_struct.do_filter],PNG_FILTER_PAETH |
1317 | mov byte[edi+png_struct.do_filter],PNG_FILTER_PAETH |
1318 | jmp .end1 |
1318 | jmp .end1 |
1319 | @@: ;default: |
1319 | @@: ;default: |
1320 | mov eax,[filters] |
1320 | mov eax,[filters] |
1321 | mov byte[edi+png_struct.do_filter],al |
1321 | mov byte[edi+png_struct.do_filter],al |
1322 | jmp .end1 |
1322 | jmp .end1 |
1323 | else |
1323 | else |
1324 | @@: ;default: |
1324 | @@: ;default: |
1325 | cStr ,'Unknown row filter for method 0' |
1325 | cStr ,'Unknown row filter for method 0' |
1326 | stdcall png_app_error edi, eax |
1326 | stdcall png_app_error edi, eax |
1327 | end if ;WRITE_FILTER |
1327 | end if ;WRITE_FILTER |
1328 | .end1: |
1328 | .end1: |
1329 | 1329 | ||
1330 | if PNG_WRITE_FILTER_SUPPORTED eq 1 |
1330 | if PNG_WRITE_FILTER_SUPPORTED eq 1 |
1331 | ; If we have allocated the row_buf, this means we have already started |
1331 | ; If we have allocated the row_buf, this means we have already started |
1332 | ; with the image and we should have allocated all of the filter buffers |
1332 | ; with the image and we should have allocated all of the filter buffers |
1333 | ; that have been selected. If prev_row isn't already allocated, then |
1333 | ; that have been selected. If prev_row isn't already allocated, then |
1334 | ; it is too late to start using the filters that need it, since we |
1334 | ; it is too late to start using the filters that need it, since we |
1335 | ; will be missing the data in the previous row. If an application |
1335 | ; will be missing the data in the previous row. If an application |
1336 | ; wants to start and stop using particular filters during compression, |
1336 | ; wants to start and stop using particular filters during compression, |
1337 | ; it should start out with all of the filters, and then remove them |
1337 | ; it should start out with all of the filters, and then remove them |
1338 | ; or add them back after the start of compression. |
1338 | ; or add them back after the start of compression. |
1339 | 1339 | ||
1340 | ; NOTE: this is a nasty constraint on the code, because it means that the |
1340 | ; NOTE: this is a nasty constraint on the code, because it means that the |
1341 | ; prev_row buffer must be maintained even if there are currently no |
1341 | ; prev_row buffer must be maintained even if there are currently no |
1342 | ; 'prev_row' requiring filters active. |
1342 | ; 'prev_row' requiring filters active. |
1343 | 1343 | ||
1344 | cmp dword[edi+png_struct.row_buf],0 |
1344 | cmp dword[edi+png_struct.row_buf],0 |
1345 | je .end3 ;if (..!=0) |
1345 | je .end3 ;if (..!=0) |
1346 | ;ebx = num_filters |
1346 | ;ebx = num_filters |
1347 | ;ecx = buf_size |
1347 | ;ecx = buf_size |
1348 | 1348 | ||
1349 | ; Repeat the checks in png_write_start_row; 1 pixel high or wide |
1349 | ; Repeat the checks in png_write_start_row; 1 pixel high or wide |
1350 | ; images cannot benefit from certain filters. If this isn't done here |
1350 | ; images cannot benefit from certain filters. If this isn't done here |
1351 | ; the check below will fire on 1 pixel high images. |
1351 | ; the check below will fire on 1 pixel high images. |
1352 | 1352 | ||
1353 | cmp dword[edi+png_struct.height],1 |
1353 | cmp dword[edi+png_struct.height],1 |
1354 | jne @f ;if (..==..) |
1354 | jne @f ;if (..==..) |
1355 | and dword[filters],not (PNG_FILTER_UP or PNG_FILTER_AVG or PNG_FILTER_PAETH) |
1355 | and dword[filters],not (PNG_FILTER_UP or PNG_FILTER_AVG or PNG_FILTER_PAETH) |
1356 | @@: |
1356 | @@: |
1357 | cmp dword[edi+png_struct.width],1 |
1357 | cmp dword[edi+png_struct.width],1 |
1358 | jne @f ;if (..==..) |
1358 | jne @f ;if (..==..) |
1359 | and dword[filters],not (PNG_FILTER_SUB or PNG_FILTER_AVG or PNG_FILTER_PAETH) |
1359 | and dword[filters],not (PNG_FILTER_SUB or PNG_FILTER_AVG or PNG_FILTER_PAETH) |
1360 | @@: |
1360 | @@: |
1361 | mov eax,[filters] |
1361 | mov eax,[filters] |
1362 | and eax,PNG_FILTER_UP or PNG_FILTER_AVG or PNG_FILTER_PAETH |
1362 | and eax,PNG_FILTER_UP or PNG_FILTER_AVG or PNG_FILTER_PAETH |
1363 | jz @f |
1363 | jz @f |
1364 | cmp dword[edi+png_struct.prev_row],0 |
1364 | cmp dword[edi+png_struct.prev_row],0 |
1365 | je @f;if (..!=0 && ..==0) |
1365 | je @f;if (..!=0 && ..==0) |
1366 | ; This is the error case, however it is benign - the previous row |
1366 | ; This is the error case, however it is benign - the previous row |
1367 | ; is not available so the filter can't be used. Just warn here. |
1367 | ; is not available so the filter can't be used. Just warn here. |
1368 | 1368 | ||
1369 | png_app_warning edi, 'png_set_filter: UP/AVG/PAETH cannot be added after start' |
1369 | png_app_warning edi, 'png_set_filter: UP/AVG/PAETH cannot be added after start' |
1370 | and dword[filters],not (PNG_FILTER_UP or PNG_FILTER_AVG or PNG_FILTER_PAETH) |
1370 | and dword[filters],not (PNG_FILTER_UP or PNG_FILTER_AVG or PNG_FILTER_PAETH) |
1371 | @@: |
1371 | @@: |
1372 | 1372 | ||
1373 | xor ebx,ebx |
1373 | xor ebx,ebx |
1374 | 1374 | ||
1375 | mov eax,[filters] |
1375 | mov eax,[filters] |
1376 | and eax,PNG_FILTER_SUB |
1376 | and eax,PNG_FILTER_SUB |
1377 | jz @f ;if (..) |
1377 | jz @f ;if (..) |
1378 | inc ebx |
1378 | inc ebx |
1379 | @@: |
1379 | @@: |
1380 | mov eax,[filters] |
1380 | mov eax,[filters] |
1381 | and eax,PNG_FILTER_UP |
1381 | and eax,PNG_FILTER_UP |
1382 | jz @f ;if (..) |
1382 | jz @f ;if (..) |
1383 | inc ebx |
1383 | inc ebx |
1384 | @@: |
1384 | @@: |
1385 | mov eax,[filters] |
1385 | mov eax,[filters] |
1386 | and eax,PNG_FILTER_AVG |
1386 | and eax,PNG_FILTER_AVG |
1387 | jz @f ;if (..) |
1387 | jz @f ;if (..) |
1388 | inc ebx |
1388 | inc ebx |
1389 | @@: |
1389 | @@: |
1390 | mov eax,[filters] |
1390 | mov eax,[filters] |
1391 | and eax,PNG_FILTER_PAETH |
1391 | and eax,PNG_FILTER_PAETH |
1392 | jz @f ;if (..) |
1392 | jz @f ;if (..) |
1393 | inc ebx |
1393 | inc ebx |
1394 | @@: |
1394 | @@: |
1395 | ; Allocate needed row buffers if they have not already been |
1395 | ; Allocate needed row buffers if they have not already been |
1396 | ; allocated. |
1396 | ; allocated. |
1397 | 1397 | ||
1398 | movzx eax,byte[edi+png_struct.usr_channels] |
1398 | movzx eax,byte[edi+png_struct.usr_channels] |
1399 | movzx ecx,byte[edi+png_struct.usr_bit_depth] |
1399 | movzx ecx,byte[edi+png_struct.usr_bit_depth] |
1400 | imul eax,ecx ;.bit_depth * .channels |
1400 | imul eax,ecx ;.bit_depth * .channels |
1401 | mov ecx,[edi+png_struct.width] |
1401 | mov ecx,[edi+png_struct.width] |
1402 | inc ecx |
1402 | inc ecx |
1403 | PNG_ROWBYTES eax, ecx |
1403 | PNG_ROWBYTES eax, ecx |
1404 | mov ecx, eax |
1404 | mov ecx, eax |
1405 | 1405 | ||
1406 | cmp dword[edi+png_struct.try_row],0 |
1406 | cmp dword[edi+png_struct.try_row],0 |
1407 | jne @f ;if (..==0) |
1407 | jne @f ;if (..==0) |
1408 | stdcall png_malloc, edi, ecx |
1408 | stdcall png_malloc, edi, ecx |
1409 | mov [edi+png_struct.try_row],eax |
1409 | mov [edi+png_struct.try_row],eax |
1410 | @@: |
1410 | @@: |
1411 | 1411 | ||
1412 | cmp ebx,1 |
1412 | cmp ebx,1 |
1413 | jle .end3 ;if (..>..) |
1413 | jle .end3 ;if (..>..) |
1414 | cmp dword[edi+png_struct.tst_row],0 |
1414 | cmp dword[edi+png_struct.tst_row],0 |
1415 | jne .end3 ;if (..==0) |
1415 | jne .end3 ;if (..==0) |
1416 | stdcall png_malloc, edi, ecx |
1416 | stdcall png_malloc, edi, ecx |
1417 | mov [edi+png_struct.tst_row],eax |
1417 | mov [edi+png_struct.tst_row],eax |
1418 | .end3: |
1418 | .end3: |
1419 | mov eax,[filters] |
1419 | mov eax,[filters] |
1420 | mov byte[edi+png_struct.do_filter],al |
1420 | mov byte[edi+png_struct.do_filter],al |
1421 | end if |
1421 | end if |
1422 | jmp .end_f |
1422 | jmp .end_f |
1423 | .end0: ;else |
1423 | .end0: ;else |
1424 | png_error edi, 'Unknown custom filter method' |
1424 | png_error edi, 'Unknown custom filter method' |
1425 | .end_f: |
1425 | .end_f: |
1426 | popad |
1426 | popad |
1427 | ret |
1427 | ret |
1428 | endp |
1428 | endp |
1429 | 1429 | ||
1430 | ; Provide floating and fixed point APIs |
1430 | ; Provide floating and fixed point APIs |
1431 | ;void (png_structrp png_ptr, int heuristic_method, |
1431 | ;void (png_structrp png_ptr, int heuristic_method, |
1432 | ; int num_weights, png_const_doublep filter_weights, png_const_doublep filter_costs) |
1432 | ; int num_weights, png_const_doublep filter_weights, png_const_doublep filter_costs) |
1433 | align 4 |
1433 | align 4 |
1434 | proc png_set_filter_heuristics, png_ptr:dword, heuristic_method:dword, num_weights:dword, filter_weights:dword, filter_costs:dword |
1434 | proc png_set_filter_heuristics, png_ptr:dword, heuristic_method:dword, num_weights:dword, filter_weights:dword, filter_costs:dword |
1435 | ret |
1435 | ret |
1436 | endp |
1436 | endp |
1437 | 1437 | ||
1438 | ;void (png_structrp png_ptr, int heuristic_method, |
1438 | ;void (png_structrp png_ptr, int heuristic_method, |
1439 | ; int num_weights, png_const_fixed_point_p filter_weights, |
1439 | ; int num_weights, png_const_fixed_point_p filter_weights, |
1440 | ; png_const_fixed_point_p filter_costs) |
1440 | ; png_const_fixed_point_p filter_costs) |
1441 | align 4 |
1441 | align 4 |
1442 | proc png_set_filter_heuristics_fixed, png_ptr:dword, heuristic_method:dword, num_weights:dword, filter_weights:dword, filter_costs:dword |
1442 | proc png_set_filter_heuristics_fixed, png_ptr:dword, heuristic_method:dword, num_weights:dword, filter_weights:dword, filter_costs:dword |
1443 | ret |
1443 | ret |
1444 | endp |
1444 | endp |
1445 | 1445 | ||
1446 | ;void (png_structrp png_ptr, int level) |
1446 | ;void (png_structrp png_ptr, int level) |
1447 | align 4 |
1447 | align 4 |
1448 | proc png_set_compression_level uses edi, png_ptr:dword, level:dword |
1448 | proc png_set_compression_level uses edi, png_ptr:dword, level:dword |
1449 | png_debug 1, 'in png_set_compression_level' |
1449 | png_debug 1, 'in png_set_compression_level' |
1450 | 1450 | ||
1451 | mov edi,[png_ptr] |
1451 | mov edi,[png_ptr] |
1452 | cmp edi,0 |
1452 | cmp edi,0 |
1453 | je @f ;if (..==0) return |
1453 | je @f ;if (..==0) return |
1454 | 1454 | ||
1455 | m2m [edi+png_struct.zlib_level], [level] |
1455 | m2m [edi+png_struct.zlib_level], [level] |
1456 | @@: |
1456 | @@: |
1457 | ret |
1457 | ret |
1458 | endp |
1458 | endp |
1459 | 1459 | ||
1460 | ;void (png_structrp png_ptr, int mem_level) |
1460 | ;void (png_structrp png_ptr, int mem_level) |
1461 | align 4 |
1461 | align 4 |
1462 | proc png_set_compression_mem_level uses edi, png_ptr:dword, mem_level:dword |
1462 | proc png_set_compression_mem_level uses edi, png_ptr:dword, mem_level:dword |
1463 | png_debug 1, 'in png_set_compression_mem_level' |
1463 | png_debug 1, 'in png_set_compression_mem_level' |
1464 | 1464 | ||
1465 | mov edi,[png_ptr] |
1465 | mov edi,[png_ptr] |
1466 | cmp edi,0 |
1466 | cmp edi,0 |
1467 | je @f ;if (..==0) return |
1467 | je @f ;if (..==0) return |
1468 | 1468 | ||
1469 | m2m [edi+png_struct.zlib_mem_level], [mem_level] |
1469 | m2m [edi+png_struct.zlib_mem_level], [mem_level] |
1470 | @@: |
1470 | @@: |
1471 | ret |
1471 | ret |
1472 | endp |
1472 | endp |
1473 | 1473 | ||
1474 | ;void (png_structrp png_ptr, int strategy) |
1474 | ;void (png_structrp png_ptr, int strategy) |
1475 | align 4 |
1475 | align 4 |
1476 | proc png_set_compression_strategy uses edi, png_ptr:dword, strategy:dword |
1476 | proc png_set_compression_strategy uses edi, png_ptr:dword, strategy:dword |
1477 | png_debug 1, 'in png_set_compression_strategy' |
1477 | png_debug 1, 'in png_set_compression_strategy' |
1478 | 1478 | ||
1479 | mov edi,[png_ptr] |
1479 | mov edi,[png_ptr] |
1480 | cmp edi,0 |
1480 | cmp edi,0 |
1481 | je .end_f ;if (..==0) return |
1481 | je .end_f ;if (..==0) return |
1482 | 1482 | ||
1483 | ; The flag setting here prevents the libpng dynamic selection of strategy. |
1483 | ; The flag setting here prevents the libpng dynamic selection of strategy. |
1484 | 1484 | ||
1485 | or dword[edi+png_struct.flags], PNG_FLAG_ZLIB_CUSTOM_STRATEGY |
1485 | or dword[edi+png_struct.flags], PNG_FLAG_ZLIB_CUSTOM_STRATEGY |
1486 | m2m [edi+png_struct.zlib_strategy], [strategy] |
1486 | m2m [edi+png_struct.zlib_strategy], [strategy] |
1487 | .end_f: |
1487 | .end_f: |
1488 | ret |
1488 | ret |
1489 | endp |
1489 | endp |
1490 | 1490 | ||
1491 | ; If PNG_WRITE_OPTIMIZE_CMF_SUPPORTED is defined, libpng will use a |
1491 | ; If PNG_WRITE_OPTIMIZE_CMF_SUPPORTED is defined, libpng will use a |
1492 | ; smaller value of window_bits if it can do so safely. |
1492 | ; smaller value of window_bits if it can do so safely. |
1493 | 1493 | ||
1494 | ;void (png_structrp png_ptr, int window_bits) |
1494 | ;void (png_structrp png_ptr, int window_bits) |
1495 | align 4 |
1495 | align 4 |
1496 | proc png_set_compression_window_bits uses eax edi, png_ptr:dword, window_bits:dword |
1496 | proc png_set_compression_window_bits uses eax edi, png_ptr:dword, window_bits:dword |
1497 | mov edi,[png_ptr] |
1497 | mov edi,[png_ptr] |
1498 | cmp edi,0 |
1498 | cmp edi,0 |
1499 | je .end_f ;if (..==0) return |
1499 | je .end_f ;if (..==0) return |
1500 | 1500 | ||
1501 | ; Prior to 1.6.0 this would warn but then set the window_bits value. This |
1501 | ; Prior to 1.6.0 this would warn but then set the window_bits value. This |
1502 | ; meant that negative window bits values could be selected that would cause |
1502 | ; meant that negative window bits values could be selected that would cause |
1503 | ; libpng to write a non-standard PNG file with raw deflate or gzip |
1503 | ; libpng to write a non-standard PNG file with raw deflate or gzip |
1504 | ; compressed IDAT or ancillary chunks. Such files can be read and there is |
1504 | ; compressed IDAT or ancillary chunks. Such files can be read and there is |
1505 | ; no warning on read, so this seems like a very bad idea. |
1505 | ; no warning on read, so this seems like a very bad idea. |
1506 | 1506 | ||
1507 | mov eax,[window_bits] |
1507 | mov eax,[window_bits] |
1508 | cmp eax,15 |
1508 | cmp eax,15 |
1509 | jle @f ;if (..>..) |
1509 | jle @f ;if (..>..) |
1510 | png_warning edi, 'Only compression windows <= 32k supported by PNG' |
1510 | png_warning edi, 'Only compression windows <= 32k supported by PNG' |
1511 | mov eax,15 |
1511 | mov eax,15 |
1512 | jmp .end0 |
1512 | jmp .end0 |
1513 | @@: ;else if (..<..) |
1513 | @@: ;else if (..<..) |
1514 | cmp eax,8 |
1514 | cmp eax,8 |
1515 | jge @f |
1515 | jge @f |
1516 | png_warning edi, 'Only compression windows >= 256 supported by PNG' |
1516 | png_warning edi, 'Only compression windows >= 256 supported by PNG' |
1517 | mov eax,8 |
1517 | mov eax,8 |
1518 | .end0: |
1518 | .end0: |
1519 | 1519 | ||
1520 | mov [edi+png_struct.zlib_window_bits],eax |
1520 | mov [edi+png_struct.zlib_window_bits],eax |
1521 | .end_f: |
1521 | .end_f: |
1522 | ret |
1522 | ret |
1523 | endp |
1523 | endp |
1524 | 1524 | ||
1525 | ;void (png_structrp png_ptr, int method) |
1525 | ;void (png_structrp png_ptr, int method) |
1526 | align 4 |
1526 | align 4 |
1527 | proc png_set_compression_method uses eax edi, png_ptr:dword, method:dword |
1527 | proc png_set_compression_method uses eax edi, png_ptr:dword, method:dword |
1528 | png_debug 1, 'in png_set_compression_method' |
1528 | png_debug 1, 'in png_set_compression_method' |
1529 | 1529 | ||
1530 | mov edi,[png_ptr] |
1530 | mov edi,[png_ptr] |
1531 | cmp edi,0 |
1531 | cmp edi,0 |
1532 | je .end_f ;if (..==0) return |
1532 | je .end_f ;if (..==0) return |
1533 | 1533 | ||
1534 | ; This would produce an invalid PNG file if it worked, but it doesn't and |
1534 | ; This would produce an invalid PNG file if it worked, but it doesn't and |
1535 | ; deflate will fault it, so it is harmless to just warn here. |
1535 | ; deflate will fault it, so it is harmless to just warn here. |
1536 | 1536 | ||
1537 | mov eax,[method] |
1537 | mov eax,[method] |
1538 | cmp eax,8 |
1538 | cmp eax,8 |
1539 | je @f ;if (..!=..) |
1539 | je @f ;if (..!=..) |
1540 | png_warning edi, 'Only compression method 8 is supported by PNG' |
1540 | png_warning edi, 'Only compression method 8 is supported by PNG' |
1541 | @@: |
1541 | @@: |
1542 | mov [edi+png_struct.zlib_method],eax |
1542 | mov [edi+png_struct.zlib_method],eax |
1543 | .end_f: |
1543 | .end_f: |
1544 | ret |
1544 | ret |
1545 | endp |
1545 | endp |
1546 | 1546 | ||
1547 | ; The following were added to libpng-1.5.4 |
1547 | ; The following were added to libpng-1.5.4 |
1548 | if PNG_WRITE_CUSTOMIZE_ZTXT_COMPRESSION_SUPPORTED eq 1 |
1548 | if PNG_WRITE_CUSTOMIZE_ZTXT_COMPRESSION_SUPPORTED eq 1 |
1549 | ;void (png_structrp png_ptr, int level) |
1549 | ;void (png_structrp png_ptr, int level) |
1550 | align 4 |
1550 | align 4 |
1551 | proc png_set_text_compression_level uses edi, png_ptr:dword, level:dword |
1551 | proc png_set_text_compression_level uses edi, png_ptr:dword, level:dword |
1552 | png_debug 1, 'in png_set_text_compression_level' |
1552 | png_debug 1, 'in png_set_text_compression_level' |
1553 | 1553 | ||
1554 | mov edi,[png_ptr] |
1554 | mov edi,[png_ptr] |
1555 | cmp edi,0 |
1555 | cmp edi,0 |
1556 | je @f ;if (..==0) return |
1556 | je @f ;if (..==0) return |
1557 | 1557 | ||
1558 | m2m [edi+png_struct.zlib_text_level], [level] |
1558 | m2m [edi+png_struct.zlib_text_level], [level] |
1559 | @@: |
1559 | @@: |
1560 | ret |
1560 | ret |
1561 | endp |
1561 | endp |
1562 | 1562 | ||
1563 | ;void (png_structrp png_ptr, int mem_level) |
1563 | ;void (png_structrp png_ptr, int mem_level) |
1564 | align 4 |
1564 | align 4 |
1565 | proc png_set_text_compression_mem_level uses edi, png_ptr:dword, mem_level:dword |
1565 | proc png_set_text_compression_mem_level uses edi, png_ptr:dword, mem_level:dword |
1566 | png_debug 1, 'in png_set_text_compression_mem_level' |
1566 | png_debug 1, 'in png_set_text_compression_mem_level' |
1567 | 1567 | ||
1568 | mov edi,[png_ptr] |
1568 | mov edi,[png_ptr] |
1569 | cmp edi,0 |
1569 | cmp edi,0 |
1570 | je @f ;if (..==0) return |
1570 | je @f ;if (..==0) return |
1571 | 1571 | ||
1572 | m2m [edi+png_struct.zlib_text_mem_level], [mem_level] |
1572 | m2m [edi+png_struct.zlib_text_mem_level], [mem_level] |
1573 | @@: |
1573 | @@: |
1574 | ret |
1574 | ret |
1575 | endp |
1575 | endp |
1576 | 1576 | ||
1577 | ;void (png_structrp png_ptr, int strategy) |
1577 | ;void (png_structrp png_ptr, int strategy) |
1578 | align 4 |
1578 | align 4 |
1579 | proc png_set_text_compression_strategy uses edi, png_ptr:dword, strategy:dword |
1579 | proc png_set_text_compression_strategy uses edi, png_ptr:dword, strategy:dword |
1580 | png_debug 1, 'in png_set_text_compression_strategy' |
1580 | png_debug 1, 'in png_set_text_compression_strategy' |
1581 | 1581 | ||
1582 | mov edi,[png_ptr] |
1582 | mov edi,[png_ptr] |
1583 | cmp edi,0 |
1583 | cmp edi,0 |
1584 | je .end_f ;if (..==0) return |
1584 | je .end_f ;if (..==0) return |
1585 | 1585 | ||
1586 | m2m [edi+png_struct.zlib_text_strategy], [strategy] |
1586 | m2m [edi+png_struct.zlib_text_strategy], [strategy] |
1587 | .end_f: |
1587 | .end_f: |
1588 | ret |
1588 | ret |
1589 | endp |
1589 | endp |
1590 | 1590 | ||
1591 | ; If PNG_WRITE_OPTIMIZE_CMF_SUPPORTED is defined, libpng will use a |
1591 | ; If PNG_WRITE_OPTIMIZE_CMF_SUPPORTED is defined, libpng will use a |
1592 | ; smaller value of window_bits if it can do so safely. |
1592 | ; smaller value of window_bits if it can do so safely. |
1593 | 1593 | ||
1594 | ;void (png_structrp png_ptr, int window_bits) |
1594 | ;void (png_structrp png_ptr, int window_bits) |
1595 | align 4 |
1595 | align 4 |
1596 | proc png_set_text_compression_window_bits uses eax edi, png_ptr:dword, window_bits:dword |
1596 | proc png_set_text_compression_window_bits uses eax edi, png_ptr:dword, window_bits:dword |
1597 | mov edi,[png_ptr] |
1597 | mov edi,[png_ptr] |
1598 | cmp edi,0 |
1598 | cmp edi,0 |
1599 | je .end_f ;if (..==0) return |
1599 | je .end_f ;if (..==0) return |
1600 | 1600 | ||
1601 | mov eax,[window_bits] |
1601 | mov eax,[window_bits] |
1602 | cmp eax,15 |
1602 | cmp eax,15 |
1603 | jle @f ;if (..>..) |
1603 | jle @f ;if (..>..) |
1604 | png_warning edi, 'Only compression windows <= 32k supported by PNG' |
1604 | png_warning edi, 'Only compression windows <= 32k supported by PNG' |
1605 | mov eax,15 |
1605 | mov eax,15 |
1606 | jmp .end0 |
1606 | jmp .end0 |
1607 | @@: ;else if (..<..) |
1607 | @@: ;else if (..<..) |
1608 | cmp eax,8 |
1608 | cmp eax,8 |
1609 | jge @f |
1609 | jge @f |
1610 | png_warning edi, 'Only compression windows >= 256 supported by PNG' |
1610 | png_warning edi, 'Only compression windows >= 256 supported by PNG' |
1611 | mov eax,8 |
1611 | mov eax,8 |
1612 | .end0: |
1612 | .end0: |
1613 | 1613 | ||
1614 | mov [edi+png_struct.zlib_text_window_bits],eax |
1614 | mov [edi+png_struct.zlib_text_window_bits],eax |
1615 | .end_f: |
1615 | .end_f: |
1616 | ret |
1616 | ret |
1617 | endp |
1617 | endp |
1618 | 1618 | ||
1619 | ;void (png_structrp png_ptr, int method) |
1619 | ;void (png_structrp png_ptr, int method) |
1620 | align 4 |
1620 | align 4 |
1621 | proc png_set_text_compression_method uses edi, png_ptr:dword, method:dword |
1621 | proc png_set_text_compression_method uses edi, png_ptr:dword, method:dword |
1622 | png_debug 1, 'in png_set_text_compression_method' |
1622 | png_debug 1, 'in png_set_text_compression_method' |
1623 | 1623 | ||
1624 | mov edi,[png_ptr] |
1624 | mov edi,[png_ptr] |
1625 | cmp edi,0 |
1625 | cmp edi,0 |
1626 | je .end_f ;if (..==0) return |
1626 | je .end_f ;if (..==0) return |
1627 | 1627 | ||
1628 | cmp dword[method],8 |
1628 | cmp dword[method],8 |
1629 | je @f ;if (..!=..) |
1629 | je @f ;if (..!=..) |
1630 | png_warning edi, 'Only compression method 8 is supported by PNG' |
1630 | png_warning edi, 'Only compression method 8 is supported by PNG' |
1631 | @@: |
1631 | @@: |
1632 | m2m [edi+png_struct.zlib_text_method], [method] |
1632 | m2m [edi+png_struct.zlib_text_method], [method] |
1633 | .end_f: |
1633 | .end_f: |
1634 | ret |
1634 | ret |
1635 | endp |
1635 | endp |
1636 | end if ;WRITE_CUSTOMIZE_ZTXT_COMPRESSION |
1636 | end if ;WRITE_CUSTOMIZE_ZTXT_COMPRESSION |
1637 | ; end of API added to libpng-1.5.4 |
1637 | ; end of API added to libpng-1.5.4 |
1638 | 1638 | ||
1639 | ;void (png_structrp png_ptr, png_write_status_ptr write_row_fn) |
1639 | ;void (png_structrp png_ptr, png_write_status_ptr write_row_fn) |
1640 | align 4 |
1640 | align 4 |
1641 | proc png_set_write_status_fn uses edi, png_ptr:dword, write_row_fn:dword |
1641 | proc png_set_write_status_fn uses edi, png_ptr:dword, write_row_fn:dword |
1642 | mov edi,[png_ptr] |
1642 | mov edi,[png_ptr] |
1643 | cmp edi,0 |
1643 | cmp edi,0 |
1644 | je @f ;if (..==0) return |
1644 | je @f ;if (..==0) return |
1645 | m2m [edi+png_struct.write_row_fn], [write_row_fn] |
1645 | m2m [edi+png_struct.write_row_fn], [write_row_fn] |
1646 | @@: |
1646 | @@: |
1647 | ret |
1647 | ret |
1648 | endp |
1648 | endp |
1649 | 1649 | ||
1650 | ;void (png_structrp png_ptr, png_user_transform_ptr write_user_transform_fn) |
1650 | ;void (png_structrp png_ptr, png_user_transform_ptr write_user_transform_fn) |
1651 | align 4 |
1651 | align 4 |
1652 | proc png_set_write_user_transform_fn uses edi, png_ptr:dword, write_user_transform_fn:dword |
1652 | proc png_set_write_user_transform_fn uses edi, png_ptr:dword, write_user_transform_fn:dword |
1653 | png_debug 1, 'in png_set_write_user_transform_fn' |
1653 | png_debug 1, 'in png_set_write_user_transform_fn' |
1654 | 1654 | ||
1655 | mov edi,[png_ptr] |
1655 | mov edi,[png_ptr] |
1656 | cmp edi,0 |
1656 | cmp edi,0 |
1657 | je @f ;if (..==0) return |
1657 | je @f ;if (..==0) return |
1658 | or dword[edi+png_struct.transformations], PNG_USER_TRANSFORM |
1658 | or dword[edi+png_struct.transformations], PNG_USER_TRANSFORM |
1659 | m2m [edi+png_struct.write_user_transform_fn], [write_user_transform_fn] |
1659 | m2m [edi+png_struct.write_user_transform_fn], [write_user_transform_fn] |
1660 | @@: |
1660 | @@: |
1661 | ret |
1661 | ret |
1662 | endp |
1662 | endp |
1663 | 1663 | ||
1664 | ;void (png_structrp png_ptr, png_inforp info_ptr, int transforms, voidp params) |
1664 | ;void (png_structrp png_ptr, png_inforp info_ptr, int transforms, voidp params) |
1665 | align 4 |
1665 | align 4 |
1666 | proc png_write_png, png_ptr:dword, info_ptr:dword, transforms:dword, params:dword |
1666 | proc png_write_png, png_ptr:dword, info_ptr:dword, transforms:dword, params:dword |
1667 | pushad |
1667 | pushad |
1668 | mov edi,[png_ptr] |
1668 | mov edi,[png_ptr] |
1669 | cmp edi,0 |
1669 | cmp edi,0 |
1670 | je .end_f |
1670 | je .end_f |
1671 | mov esi,[info_ptr] |
1671 | mov esi,[info_ptr] |
1672 | cmp esi,0 |
1672 | cmp esi,0 |
1673 | je .end_f ;if(..==0 || ..==0) return |
1673 | je .end_f ;if(..==0 || ..==0) return |
1674 | 1674 | ||
1675 | and dword[esi+png_info_def.valid],PNG_INFO_IDAT |
1675 | and dword[esi+png_info_def.valid],PNG_INFO_IDAT |
1676 | cmp esi,0 ;if(..==0) |
1676 | cmp esi,0 ;if(..==0) |
1677 | jne @f |
1677 | jne @f |
1678 | cStr ,'no rows for png_write_image to write' |
1678 | cStr ,'no rows for png_write_image to write' |
1679 | stdcall png_app_error edi, eax |
1679 | stdcall png_app_error edi, eax |
1680 | jmp .end_f ;return |
1680 | jmp .end_f ;return |
1681 | @@: |
1681 | @@: |
1682 | 1682 | ||
1683 | ; Write the file header information. |
1683 | ; Write the file header information. |
1684 | stdcall png_write_info, edi, esi |
1684 | stdcall png_write_info, edi, esi |
1685 | 1685 | ||
1686 | ; ------ these transformations don't touch the info structure ------- |
1686 | ; ------ these transformations don't touch the info structure ------- |
1687 | 1687 | ||
1688 | ; Invert monochrome pixels |
1688 | ; Invert monochrome pixels |
1689 | mov eax,[transforms] |
1689 | mov eax,[transforms] |
1690 | and eax,PNG_TRANSFORM_INVERT_MONO |
1690 | and eax,PNG_TRANSFORM_INVERT_MONO |
1691 | jz @f ;if(..!=0) |
1691 | jz @f ;if(..!=0) |
1692 | if PNG_WRITE_INVERT_SUPPORTED eq 1 |
1692 | if PNG_WRITE_INVERT_SUPPORTED eq 1 |
1693 | stdcall png_set_invert_mono,edi |
1693 | stdcall png_set_invert_mono,edi |
1694 | else |
1694 | else |
1695 | cStr ,'PNG_TRANSFORM_INVERT_MONO not supported' |
1695 | cStr ,'PNG_TRANSFORM_INVERT_MONO not supported' |
1696 | stdcall png_app_error edi, eax |
1696 | stdcall png_app_error edi, eax |
1697 | end if |
1697 | end if |
1698 | @@: |
1698 | @@: |
1699 | 1699 | ||
1700 | ; Shift the pixels up to a legal bit depth and fill in |
1700 | ; Shift the pixels up to a legal bit depth and fill in |
1701 | ; as appropriate to correctly scale the image. |
1701 | ; as appropriate to correctly scale the image. |
1702 | 1702 | ||
1703 | mov eax,[transforms] |
1703 | mov eax,[transforms] |
1704 | and eax,PNG_TRANSFORM_SHIFT |
1704 | and eax,PNG_TRANSFORM_SHIFT |
1705 | jz @f ;if(..!=0) |
1705 | jz @f ;if(..!=0) |
1706 | if PNG_WRITE_SHIFT_SUPPORTED eq 1 |
1706 | if PNG_WRITE_SHIFT_SUPPORTED eq 1 |
1707 | mov eax,[esi+png_info_def.valid] |
1707 | mov eax,[esi+png_info_def.valid] |
1708 | and eax,PNG_INFO_sBIT |
1708 | and eax,PNG_INFO_sBIT |
1709 | jz @f ;if(..!=0) |
1709 | jz @f ;if(..!=0) |
1710 | mov eax,esi |
1710 | mov eax,esi |
1711 | add eax,png_info_def.sig_bit |
1711 | add eax,png_info_def.sig_bit |
1712 | stdcall png_set_shift, edi, eax |
1712 | stdcall png_set_shift, edi, eax |
1713 | else |
1713 | else |
1714 | cStr ,'PNG_TRANSFORM_SHIFT not supported' |
1714 | cStr ,'PNG_TRANSFORM_SHIFT not supported' |
1715 | stdcall png_app_error edi, eax |
1715 | stdcall png_app_error edi, eax |
1716 | end if |
1716 | end if |
1717 | @@: |
1717 | @@: |
1718 | 1718 | ||
1719 | ; Pack pixels into bytes |
1719 | ; Pack pixels into bytes |
1720 | mov eax,[transforms] |
1720 | mov eax,[transforms] |
1721 | and eax,PNG_TRANSFORM_PACKING |
1721 | and eax,PNG_TRANSFORM_PACKING |
1722 | jz @f ;if(..!=0) |
1722 | jz @f ;if(..!=0) |
1723 | if PNG_WRITE_PACK_SUPPORTED eq 1 |
1723 | if PNG_WRITE_PACK_SUPPORTED eq 1 |
1724 | stdcall png_set_packing, edi |
1724 | stdcall png_set_packing, edi |
1725 | else |
1725 | else |
1726 | cStr ,'PNG_TRANSFORM_PACKING not supported' |
1726 | cStr ,'PNG_TRANSFORM_PACKING not supported' |
1727 | stdcall png_app_error edi, eax |
1727 | stdcall png_app_error edi, eax |
1728 | end if |
1728 | end if |
1729 | @@: |
1729 | @@: |
1730 | 1730 | ||
1731 | ; Swap location of alpha bytes from ARGB to RGBA |
1731 | ; Swap location of alpha bytes from ARGB to RGBA |
1732 | mov eax,[transforms] |
1732 | mov eax,[transforms] |
1733 | and eax,PNG_TRANSFORM_SWAP_ALPHA |
1733 | and eax,PNG_TRANSFORM_SWAP_ALPHA |
1734 | jz @f ;if(..!=0) |
1734 | jz @f ;if(..!=0) |
1735 | if PNG_WRITE_SWAP_ALPHA_SUPPORTED eq 1 |
1735 | if PNG_WRITE_SWAP_ALPHA_SUPPORTED eq 1 |
1736 | stdcall png_set_swap_alpha, edi |
1736 | stdcall png_set_swap_alpha, edi |
1737 | else |
1737 | else |
1738 | cStr ,'PNG_TRANSFORM_SWAP_ALPHA not supported' |
1738 | cStr ,'PNG_TRANSFORM_SWAP_ALPHA not supported' |
1739 | stdcall png_app_error edi, eax |
1739 | stdcall png_app_error edi, eax |
1740 | end if |
1740 | end if |
1741 | @@: |
1741 | @@: |
1742 | 1742 | ||
1743 | ; Remove a filler (X) from XRGB/RGBX/AG/GA into to convert it into |
1743 | ; Remove a filler (X) from XRGB/RGBX/AG/GA into to convert it into |
1744 | ; RGB, note that the code expects the input color type to be G or RGB; no |
1744 | ; RGB, note that the code expects the input color type to be G or RGB; no |
1745 | ; alpha channel. |
1745 | ; alpha channel. |
1746 | 1746 | ||
1747 | mov eax,[transforms] |
1747 | mov eax,[transforms] |
1748 | and eax,PNG_TRANSFORM_STRIP_FILLER_AFTER or PNG_TRANSFORM_STRIP_FILLER_BEFORE |
1748 | and eax,PNG_TRANSFORM_STRIP_FILLER_AFTER or PNG_TRANSFORM_STRIP_FILLER_BEFORE |
1749 | jz .end_0 ;if(..!=0) |
1749 | jz .end_0 ;if(..!=0) |
1750 | if PNG_WRITE_FILLER_SUPPORTED eq 1 |
1750 | if PNG_WRITE_FILLER_SUPPORTED eq 1 |
1751 | and eax,PNG_TRANSFORM_STRIP_FILLER_AFTER |
1751 | and eax,PNG_TRANSFORM_STRIP_FILLER_AFTER |
1752 | jz .end_1 ;if(..!=0) |
1752 | jz .end_1 ;if(..!=0) |
1753 | mov eax,[transforms] |
1753 | mov eax,[transforms] |
1754 | and eax,PNG_TRANSFORM_STRIP_FILLER_BEFORE |
1754 | and eax,PNG_TRANSFORM_STRIP_FILLER_BEFORE |
1755 | jz @f ;if(..!=0) |
1755 | jz @f ;if(..!=0) |
1756 | cStr ,'PNG_TRANSFORM_STRIP_FILLER: BEFORE+AFTER not supported' |
1756 | cStr ,'PNG_TRANSFORM_STRIP_FILLER: BEFORE+AFTER not supported' |
1757 | stdcall png_app_error edi, eax |
1757 | stdcall png_app_error edi, eax |
1758 | @@: |
1758 | @@: |
1759 | 1759 | ||
1760 | ; Continue if ignored - this is the pre-1.6.10 behavior |
1760 | ; Continue if ignored - this is the pre-1.6.10 behavior |
1761 | stdcall png_set_filler, edi, 0, PNG_FILLER_AFTER |
1761 | stdcall png_set_filler, edi, 0, PNG_FILLER_AFTER |
1762 | jmp .end_0 |
1762 | jmp .end_0 |
1763 | .end_1: ;else if ((transforms & PNG_TRANSFORM_STRIP_FILLER_BEFORE) != 0) |
1763 | .end_1: ;else if ((transforms & PNG_TRANSFORM_STRIP_FILLER_BEFORE) != 0) |
1764 | stdcall png_set_filler, edi, 0, PNG_FILLER_BEFORE |
1764 | stdcall png_set_filler, edi, 0, PNG_FILLER_BEFORE |
1765 | else |
1765 | else |
1766 | cStr ,'PNG_TRANSFORM_STRIP_FILLER not supported' |
1766 | cStr ,'PNG_TRANSFORM_STRIP_FILLER not supported' |
1767 | stdcall png_app_error edi, eax |
1767 | stdcall png_app_error edi, eax |
1768 | end if |
1768 | end if |
1769 | .end_0: |
1769 | .end_0: |
1770 | 1770 | ||
1771 | ; Flip BGR pixels to RGB |
1771 | ; Flip BGR pixels to RGB |
1772 | mov eax,[transforms] |
1772 | mov eax,[transforms] |
1773 | and eax,PNG_TRANSFORM_BGR |
1773 | and eax,PNG_TRANSFORM_BGR |
1774 | jz @f ;if(..!=0) |
1774 | jz @f ;if(..!=0) |
1775 | if PNG_WRITE_BGR_SUPPORTED eq 1 |
1775 | if PNG_WRITE_BGR_SUPPORTED eq 1 |
1776 | stdcall png_set_bgr, edi |
1776 | stdcall png_set_bgr, edi |
1777 | else |
1777 | else |
1778 | cStr ,'PNG_TRANSFORM_BGR not supported' |
1778 | cStr ,'PNG_TRANSFORM_BGR not supported' |
1779 | stdcall png_app_error edi, eax |
1779 | stdcall png_app_error edi, eax |
1780 | end if |
1780 | end if |
1781 | @@: |
1781 | @@: |
1782 | 1782 | ||
1783 | ; Swap bytes of 16-bit files to most significant byte first |
1783 | ; Swap bytes of 16-bit files to most significant byte first |
1784 | mov eax,[transforms] |
1784 | mov eax,[transforms] |
1785 | and eax,PNG_TRANSFORM_SWAP_ENDIAN |
1785 | and eax,PNG_TRANSFORM_SWAP_ENDIAN |
1786 | jz @f ;if(..!=0) |
1786 | jz @f ;if(..!=0) |
1787 | if PNG_WRITE_SWAP_SUPPORTED eq 1 |
1787 | if PNG_WRITE_SWAP_SUPPORTED eq 1 |
1788 | stdcall png_set_swap, edi |
1788 | stdcall png_set_swap, edi |
1789 | else |
1789 | else |
1790 | cStr ,'PNG_TRANSFORM_SWAP_ENDIAN not supported' |
1790 | cStr ,'PNG_TRANSFORM_SWAP_ENDIAN not supported' |
1791 | stdcall png_app_error edi, eax |
1791 | stdcall png_app_error edi, eax |
1792 | end if |
1792 | end if |
1793 | @@: |
1793 | @@: |
1794 | 1794 | ||
1795 | ; Swap bits of 1-bit, 2-bit, 4-bit packed pixel formats |
1795 | ; Swap bits of 1-bit, 2-bit, 4-bit packed pixel formats |
1796 | mov eax,[transforms] |
1796 | mov eax,[transforms] |
1797 | and eax,PNG_TRANSFORM_PACKSWAP |
1797 | and eax,PNG_TRANSFORM_PACKSWAP |
1798 | jz @f ;if(..!=0) |
1798 | jz @f ;if(..!=0) |
1799 | if PNG_WRITE_PACKSWAP_SUPPORTED eq 1 |
1799 | if PNG_WRITE_PACKSWAP_SUPPORTED eq 1 |
1800 | stdcall png_set_packswap, edi |
1800 | stdcall png_set_packswap, edi |
1801 | else |
1801 | else |
1802 | cStr ,'PNG_TRANSFORM_PACKSWAP not supported' |
1802 | cStr ,'PNG_TRANSFORM_PACKSWAP not supported' |
1803 | stdcall png_app_error edi, eax |
1803 | stdcall png_app_error edi, eax |
1804 | end if |
1804 | end if |
1805 | @@: |
1805 | @@: |
1806 | 1806 | ||
1807 | ; Invert the alpha channel from opacity to transparency |
1807 | ; Invert the alpha channel from opacity to transparency |
1808 | mov eax,[transforms] |
1808 | mov eax,[transforms] |
1809 | and eax,PNG_TRANSFORM_INVERT_ALPHA |
1809 | and eax,PNG_TRANSFORM_INVERT_ALPHA |
1810 | jz @f ;if(..!=0) |
1810 | jz @f ;if(..!=0) |
1811 | if PNG_WRITE_INVERT_ALPHA_SUPPORTED eq 1 |
1811 | if PNG_WRITE_INVERT_ALPHA_SUPPORTED eq 1 |
1812 | stdcall png_set_invert_alpha, edi |
1812 | stdcall png_set_invert_alpha, edi |
1813 | else |
1813 | else |
1814 | cStr ,'PNG_TRANSFORM_INVERT_ALPHA not supported' |
1814 | cStr ,'PNG_TRANSFORM_INVERT_ALPHA not supported' |
1815 | stdcall png_app_error edi, eax |
1815 | stdcall png_app_error edi, eax |
1816 | end if |
1816 | end if |
1817 | @@: |
1817 | @@: |
1818 | 1818 | ||
1819 | ; ----------------------- end of transformations ------------------- |
1819 | ; ----------------------- end of transformations ------------------- |
1820 | 1820 | ||
1821 | ; Write the bits |
1821 | ; Write the bits |
1822 | stdcall png_write_image, edi, dword[esi+png_info_def.row_pointers] |
1822 | stdcall png_write_image, edi, dword[esi+png_info_def.row_pointers] |
1823 | 1823 | ||
1824 | ; It is REQUIRED to call this to finish writing the rest of the file |
1824 | ; It is REQUIRED to call this to finish writing the rest of the file |
1825 | stdcall png_write_end, edi, esi |
1825 | stdcall png_write_end, edi, esi |
1826 | 1826 | ||
1827 | .end_f: |
1827 | .end_f: |
1828 | popad |
1828 | popad |
1829 | ret |
1829 | ret |
1830 | endp |
1830 | endp |
1831 | 1831 | ||
1832 | if PNG_SIMPLIFIED_WRITE_SUPPORTED eq 1 |
1832 | if PNG_SIMPLIFIED_WRITE_SUPPORTED eq 1 |
1833 | ; Initialize the write structure - general purpose utility. |
1833 | ; Initialize the write structure - general purpose utility. |
1834 | ;int (png_imagep image) |
1834 | ;int (png_imagep image) |
1835 | align 4 |
1835 | align 4 |
1836 | proc png_image_write_init uses ebx ecx edx edi esi, image:dword |
1836 | proc png_image_write_init uses ebx ecx edx edi esi, image:dword |
1837 | mov ebx,[image] |
1837 | mov ebx,[image] |
1838 | stdcall png_create_write_struct, PNG_LIBPNG_VER_STRING, ebx, png_safe_error, png_safe_warning |
1838 | stdcall png_create_write_struct, PNG_LIBPNG_VER_STRING, ebx, png_safe_error, png_safe_warning |
1839 | ;eax = png_ptr |
1839 | ;eax = png_ptr |
1840 | 1840 | ||
1841 | cmp eax,0 |
1841 | cmp eax,0 |
1842 | je .end0 ;if (..!=0) |
1842 | je .end0 ;if (..!=0) |
1843 | mov edi,eax |
1843 | mov edi,eax |
1844 | stdcall png_create_info_struct, edi |
1844 | stdcall png_create_info_struct, edi |
1845 | ;eax = info_ptr |
1845 | ;eax = info_ptr |
1846 | 1846 | ||
1847 | cmp eax,0 |
1847 | cmp eax,0 |
1848 | je .end1 ;if (..!=0) |
1848 | je .end1 ;if (..!=0) |
1849 | mov esi,eax |
1849 | mov esi,eax |
1850 | stdcall png_malloc_warn, edi, sizeof.png_control |
1850 | stdcall png_malloc_warn, edi, sizeof.png_control |
1851 | ;control = eax |
1851 | ;control = eax |
1852 | 1852 | ||
1853 | cmp eax,0 |
1853 | cmp eax,0 |
1854 | je .end2 ;if (..!=0) |
1854 | je .end2 ;if (..!=0) |
1855 | push eax |
1855 | push eax |
1856 | mov edx,edi ; edx = png_ptr |
1856 | mov edx,edi ; edx = png_ptr |
1857 | mov ecx,sizeof.png_control |
1857 | mov ecx,sizeof.png_control |
1858 | mov edi,eax |
1858 | mov edi,eax |
1859 | xor eax,eax |
1859 | xor eax,eax |
1860 | rep stosb ;memset(control, 0, (sizeof.control)) |
1860 | rep stosb ;memset(control, 0, (sizeof.control)) |
1861 | pop eax |
1861 | pop eax |
1862 | 1862 | ||
1863 | mov [eax+png_control.png_ptr], edx |
1863 | mov [eax+png_control.png_ptr], edx |
1864 | mov [eax+png_control.info_ptr], esi |
1864 | mov [eax+png_control.info_ptr], esi |
1865 | mov [eax+png_control.for_write], 1 |
1865 | mov [eax+png_control.for_write], 1 |
1866 | 1866 | ||
1867 | mov [ebx+png_image.opaque], eax |
1867 | mov [ebx+png_image.opaque], eax |
1868 | xor eax,eax |
1868 | xor eax,eax |
1869 | inc eax |
1869 | inc eax |
1870 | jmp .end_f |
1870 | jmp .end_f |
1871 | .end2: |
1871 | .end2: |
1872 | 1872 | ||
1873 | ; Error clean up |
1873 | ; Error clean up |
1874 | push esi |
1874 | push esi |
1875 | mov esi,esp |
1875 | mov esi,esp |
1876 | stdcall png_destroy_info_struct, edi, esi |
1876 | stdcall png_destroy_info_struct, edi, esi |
1877 | add esp,4 |
1877 | add esp,4 |
1878 | .end1: |
1878 | .end1: |
1879 | 1879 | ||
1880 | push edi |
1880 | push edi |
1881 | mov edi,esp |
1881 | mov edi,esp |
1882 | stdcall png_destroy_write_struct, edi, 0 |
1882 | stdcall png_destroy_write_struct, edi, 0 |
1883 | add esp,4 |
1883 | add esp,4 |
1884 | .end0: |
1884 | .end0: |
1885 | 1885 | ||
1886 | std_png_image_error ebx, 'png_image_write_: out of memory' |
1886 | std_png_image_error ebx, 'png_image_write_: out of memory' |
1887 | .end_f: |
1887 | .end_f: |
1888 | ret |
1888 | ret |
1889 | endp |
1889 | endp |
1890 | 1890 | ||
1891 | ; Arguments to png_image_write_main: |
1891 | ; Arguments to png_image_write_main: |
1892 | struct png_image_write_control |
1892 | struct png_image_write_control |
1893 | ; Arguments: |
1893 | ; Arguments: |
1894 | image dd ? ;png_imagep |
1894 | image dd ? ;png_imagep |
1895 | buffer dd ? ;png_const_voidp |
1895 | buffer dd ? ;png_const_voidp |
1896 | row_stride dd ? ;int_32 |
1896 | row_stride dd ? ;int_32 |
1897 | colormap dd ? ;png_const_voidp |
1897 | colormap dd ? ;png_const_voidp |
1898 | convert_to_8bit dd ? ;int |
1898 | convert_to_8bit dd ? ;int |
1899 | ; Local variables: |
1899 | ; Local variables: |
1900 | first_row dd ? ;png_const_voidp |
1900 | first_row dd ? ;png_const_voidp |
1901 | row_bytes dd ? ;ptrdiff_t |
1901 | row_bytes dd ? ;ptrdiff_t |
1902 | local_row dd ? ;voidp |
1902 | local_row dd ? ;voidp |
1903 | ; Byte count for memory writing |
1903 | ; Byte count for memory writing |
1904 | memory dd ? ;bytep |
1904 | memory dd ? ;bytep |
1905 | memory_bytes dd ? ;png_alloc_size_t ;not used for STDIO |
1905 | memory_bytes dd ? ;png_alloc_size_t ;not used for STDIO |
1906 | output_bytes dd ? ;png_alloc_size_t ;running total |
1906 | output_bytes dd ? ;png_alloc_size_t ;running total |
1907 | ends |
1907 | ends |
1908 | 1908 | ||
1909 | ; Write uint_16 input to a 16-bit PNG; the png_ptr has already been set to |
1909 | ; Write uint_16 input to a 16-bit PNG; the png_ptr has already been set to |
1910 | ; do any necessary byte swapping. The component order is defined by the |
1910 | ; do any necessary byte swapping. The component order is defined by the |
1911 | ; png_image format value. |
1911 | ; png_image format value. |
1912 | 1912 | ||
1913 | ;int (voidp argument) |
1913 | ;int (voidp argument) |
1914 | align 4 |
1914 | align 4 |
1915 | proc png_write_image_16bit uses ebx ecx edx, argument:dword |
1915 | proc png_write_image_16bit uses ebx ecx edx, argument:dword |
1916 | locals |
1916 | locals |
1917 | display dd ? ;png_image_write_control* ;= argument |
1917 | display dd ? ;png_image_write_control* ;= argument |
1918 | image dd ? ;png_imagep ;= display->image |
1918 | image dd ? ;png_imagep ;= display->image |
1919 | png_ptr dd ? ;png_structrp ;= image->opaque->png_ptr |
1919 | png_ptr dd ? ;png_structrp ;= image->opaque->png_ptr |
1920 | input_row dd ? ;const_uint_16p ;= display->first_row |
1920 | input_row dd ? ;const_uint_16p ;= display->first_row |
1921 | output_row dd ? ;uint_16p ;= display->local_row |
1921 | output_row dd ? ;uint_16p ;= display->local_row |
1922 | row_end dd ? ;uint_16p |
1922 | row_end dd ? ;uint_16p |
1923 | channels dd ? ;const int ;= (image->format & PNG_FORMAT_FLAG_COLOR) != 0 ? 3 : 1; |
1923 | channels dd ? ;const int ;= (image->format & PNG_FORMAT_FLAG_COLOR) != 0 ? 3 : 1; |
1924 | aindex dd 0 ;int ;= 0 |
1924 | aindex dd 0 ;int ;= 0 |
1925 | y dd ? ;uint_32 ;= image->height |
1925 | y dd ? ;uint_32 ;= image->height |
1926 | endl |
1926 | endl |
1927 | mov ebx,[argument] |
1927 | mov ebx,[argument] |
1928 | mov [display],ebx |
1928 | mov [display],ebx |
1929 | mov edx,[ebx+png_image_write_control.image] |
1929 | mov edx,[ebx+png_image_write_control.image] |
1930 | mov [image],edx |
1930 | mov [image],edx |
1931 | mov ecx,[edx+png_image.opaque] |
1931 | mov ecx,[edx+png_image.opaque] |
1932 | mov ecx,[ecx+png_control.png_ptr] |
1932 | mov ecx,[ecx+png_control.png_ptr] |
1933 | mov [png_ptr],ecx |
1933 | mov [png_ptr],ecx |
1934 | mov ecx,[ebx+png_image_write_control.first_row] |
1934 | mov ecx,[ebx+png_image_write_control.first_row] |
1935 | mov [input_row],ecx |
1935 | mov [input_row],ecx |
1936 | mov ecx,[ebx+png_image_write_control.local_row] |
1936 | mov ecx,[ebx+png_image_write_control.local_row] |
1937 | mov [output_row],ecx |
1937 | mov [output_row],ecx |
1938 | 1938 | ||
1939 | mov ecx,1 |
1939 | mov ecx,1 |
1940 | mov eax,[edx+png_image.format] |
1940 | mov eax,[edx+png_image.format] |
1941 | and eax,PNG_FORMAT_FLAG_COLOR |
1941 | and eax,PNG_FORMAT_FLAG_COLOR |
1942 | jz @f |
1942 | jz @f |
1943 | mov ecx,3 |
1943 | mov ecx,3 |
1944 | @@: |
1944 | @@: |
1945 | mov [channels],ecx |
1945 | mov [channels],ecx |
1946 | mov eax,[edx+png_image.height] |
1946 | mov eax,[edx+png_image.height] |
1947 | mov [y],eax |
1947 | mov [y],eax |
1948 | 1948 | ||
1949 | mov eax,[edx+png_image.format] |
1949 | mov eax,[edx+png_image.format] |
1950 | and eax,PNG_FORMAT_FLAG_ALPHA |
1950 | and eax,PNG_FORMAT_FLAG_ALPHA |
1951 | jz .end0 ;if (..!=0) |
1951 | jz .end0 ;if (..!=0) |
1952 | if PNG_SIMPLIFIED_WRITE_AFIRST_SUPPORTED eq 1 |
1952 | if PNG_SIMPLIFIED_WRITE_AFIRST_SUPPORTED eq 1 |
1953 | mov eax,[edx+png_image.format] |
1953 | mov eax,[edx+png_image.format] |
1954 | and eax,PNG_FORMAT_FLAG_AFIRST |
1954 | and eax,PNG_FORMAT_FLAG_AFIRST |
1955 | jz @f ;if (..!=0) |
1955 | jz @f ;if (..!=0) |
1956 | mov dword[aindex],-1 |
1956 | mov dword[aindex],-1 |
1957 | inc dword[input_row] ;To point to the first component |
1957 | inc dword[input_row] ;To point to the first component |
1958 | inc dword[output_row] |
1958 | inc dword[output_row] |
1959 | jmp .end1 |
1959 | jmp .end1 |
1960 | @@: ;else |
1960 | @@: ;else |
1961 | end if |
1961 | end if |
1962 | mov eax,[channels] |
1962 | mov eax,[channels] |
1963 | mov [aindex],eax |
1963 | mov [aindex],eax |
1964 | jmp .end1 |
1964 | jmp .end1 |
1965 | .end0: ;else |
1965 | .end0: ;else |
1966 | png_error [png_ptr], 'png_write_image: internal call error' |
1966 | png_error [png_ptr], 'png_write_image: internal call error' |
1967 | .end1: |
1967 | .end1: |
1968 | 1968 | ||
1969 | ; Work out the output row end and count over this, note that the increment |
1969 | ; Work out the output row end and count over this, note that the increment |
1970 | ; above to 'row' means that row_end can actually be beyond the end of the |
1970 | ; above to 'row' means that row_end can actually be beyond the end of the |
1971 | ; row; this is correct. |
1971 | ; row; this is correct. |
1972 | 1972 | ||
1973 | mov eax,[channels] |
1973 | mov eax,[channels] |
1974 | inc eax |
1974 | inc eax |
1975 | imul eax,[edx+png_image.width] |
1975 | imul eax,[edx+png_image.width] |
1976 | add eax,[output_row] |
1976 | add eax,[output_row] |
1977 | mov [row_end],eax |
1977 | mov [row_end],eax |
1978 | 1978 | ||
1979 | ; while (y-- > 0) |
1979 | ; while (y-- > 0) |
1980 | ; { |
1980 | ; { |
1981 | ; const_uint_16p in_ptr = input_row; |
1981 | ; const_uint_16p in_ptr = input_row; |
1982 | ; uint_16p out_ptr = output_row; |
1982 | ; uint_16p out_ptr = output_row; |
1983 | 1983 | ||
1984 | ; while (out_ptr < row_end) |
1984 | ; while (out_ptr < row_end) |
1985 | ; { |
1985 | ; { |
1986 | ; const uint_16 alpha = in_ptr[aindex]; |
1986 | ; const uint_16 alpha = in_ptr[aindex]; |
1987 | ; uint_32 reciprocal = 0; |
1987 | ; uint_32 reciprocal = 0; |
1988 | ; int c; |
1988 | ; int c; |
1989 | 1989 | ||
1990 | ; out_ptr[aindex] = alpha; |
1990 | ; out_ptr[aindex] = alpha; |
1991 | 1991 | ||
1992 | ; Calculate a reciprocal. The correct calculation is simply |
1992 | ; Calculate a reciprocal. The correct calculation is simply |
1993 | ; component/alpha*65535 << 15. (I.e. 15 bits of precision); this |
1993 | ; component/alpha*65535 << 15. (I.e. 15 bits of precision); this |
1994 | ; allows correct rounding by adding .5 before the shift. 'reciprocal' |
1994 | ; allows correct rounding by adding .5 before the shift. 'reciprocal' |
1995 | ; is only initialized when required. |
1995 | ; is only initialized when required. |
1996 | 1996 | ||
1997 | ; if (alpha > 0 && alpha < 65535) |
1997 | ; if (alpha > 0 && alpha < 65535) |
1998 | ; reciprocal = ((0xffff<<15)+(alpha>>1))/alpha; |
1998 | ; reciprocal = ((0xffff<<15)+(alpha>>1))/alpha; |
1999 | 1999 | ||
2000 | ; c = channels; |
2000 | ; c = channels; |
2001 | ; do /* always at least one channel */ |
2001 | ; do /* always at least one channel */ |
2002 | ; { |
2002 | ; { |
2003 | ; uint_16 component = *in_ptr++; |
2003 | ; uint_16 component = *in_ptr++; |
2004 | 2004 | ||
2005 | ; The following gives 65535 for an alpha of 0, which is fine, |
2005 | ; The following gives 65535 for an alpha of 0, which is fine, |
2006 | ; otherwise if 0/0 is represented as some other value there is more |
2006 | ; otherwise if 0/0 is represented as some other value there is more |
2007 | ; likely to be a discontinuity which will probably damage |
2007 | ; likely to be a discontinuity which will probably damage |
2008 | ; compression when moving from a fully transparent area to a |
2008 | ; compression when moving from a fully transparent area to a |
2009 | ; nearly transparent one. (The assumption here is that opaque |
2009 | ; nearly transparent one. (The assumption here is that opaque |
2010 | ; areas tend not to be 0 intensity.) |
2010 | ; areas tend not to be 0 intensity.) |
2011 | 2011 | ||
2012 | ; if (component >= alpha) |
2012 | ; if (component >= alpha) |
2013 | ; component = 65535; |
2013 | ; component = 65535; |
2014 | 2014 | ||
2015 | ; component |
2015 | ; component |
2016 | ; component*reciprocal is less than 2^31. |
2016 | ; component*reciprocal is less than 2^31. |
2017 | 2017 | ||
2018 | ; else if (component > 0 && alpha < 65535) |
2018 | ; else if (component > 0 && alpha < 65535) |
2019 | ; { |
2019 | ; { |
2020 | ; uint_32 calc = component * reciprocal; |
2020 | ; uint_32 calc = component * reciprocal; |
2021 | ; calc += 16384; /* round to nearest */ |
2021 | ; calc += 16384; /* round to nearest */ |
2022 | ; component = (uint_16)(calc >> 15); |
2022 | ; component = (uint_16)(calc >> 15); |
2023 | ; } |
2023 | ; } |
2024 | 2024 | ||
2025 | ; *out_ptr++ = component; |
2025 | ; *out_ptr++ = component; |
2026 | ; } |
2026 | ; } |
2027 | ; while (--c > 0); |
2027 | ; while (--c > 0); |
2028 | 2028 | ||
2029 | ; Skip to next component (skip the intervening alpha channel) |
2029 | ; Skip to next component (skip the intervening alpha channel) |
2030 | ; ++in_ptr; |
2030 | ; ++in_ptr; |
2031 | ; ++out_ptr; |
2031 | ; ++out_ptr; |
2032 | ; } |
2032 | ; } |
2033 | 2033 | ||
2034 | ; png_write_row(png_ptr, display->local_row); |
2034 | ; png_write_row(png_ptr, display->local_row); |
2035 | ; input_row += display->row_bytes/(sizeof (uint_16)); |
2035 | ; input_row += display->row_bytes/(sizeof (uint_16)); |
2036 | ; } |
2036 | ; } |
2037 | 2037 | ||
2038 | xor eax,eax |
2038 | xor eax,eax |
2039 | inc eax ;return 1 |
2039 | inc eax ;return 1 |
2040 | ret |
2040 | ret |
2041 | endp |
2041 | endp |
2042 | 2042 | ||
2043 | ; Given 16-bit input (1 to 4 channels) write 8-bit output. If an alpha channel |
2043 | ; Given 16-bit input (1 to 4 channels) write 8-bit output. If an alpha channel |
2044 | ; is present it must be removed from the components, the components are then |
2044 | ; is present it must be removed from the components, the components are then |
2045 | ; written in sRGB encoding. No components are added or removed. |
2045 | ; written in sRGB encoding. No components are added or removed. |
2046 | 2046 | ||
2047 | ; Calculate an alpha reciprocal to reverse pre-multiplication. As above the |
2047 | ; Calculate an alpha reciprocal to reverse pre-multiplication. As above the |
2048 | ; calculation can be done to 15 bits of accuracy; however, the output needs to |
2048 | ; calculation can be done to 15 bits of accuracy; however, the output needs to |
2049 | ; be scaled in the range 0..255*65535, so include that scaling here. |
2049 | ; be scaled in the range 0..255*65535, so include that scaling here. |
2050 | 2050 | ||
2051 | ;# define UNP_RECIPROCAL(alpha) ((((0xffff*0xff)<<7)+(alpha>>1))/alpha) |
2051 | ;# define UNP_RECIPROCAL(alpha) ((((0xffff*0xff)<<7)+(alpha>>1))/alpha) |
2052 | 2052 | ||
2053 | ;byte (uint_32 component, uint_32 alpha, uint_32 reciprocal/*from the above macro*/) |
2053 | ;byte (uint_32 component, uint_32 alpha, uint_32 reciprocal/*from the above macro*/) |
2054 | align 4 |
2054 | align 4 |
2055 | proc png_unpremultiply, component:dword, alpha:dword, reciprocal:dword |
2055 | proc png_unpremultiply, component:dword, alpha:dword, reciprocal:dword |
2056 | ; The following gives 1.0 for an alpha of 0, which is fine, otherwise if 0/0 |
2056 | ; The following gives 1.0 for an alpha of 0, which is fine, otherwise if 0/0 |
2057 | ; is represented as some other value there is more likely to be a |
2057 | ; is represented as some other value there is more likely to be a |
2058 | ; discontinuity which will probably damage compression when moving from a |
2058 | ; discontinuity which will probably damage compression when moving from a |
2059 | ; fully transparent area to a nearly transparent one. (The assumption here |
2059 | ; fully transparent area to a nearly transparent one. (The assumption here |
2060 | ; is that opaque areas tend not to be 0 intensity.) |
2060 | ; is that opaque areas tend not to be 0 intensity.) |
2061 | 2061 | ||
2062 | ; There is a rounding problem here; if alpha is less than 128 it will end up |
2062 | ; There is a rounding problem here; if alpha is less than 128 it will end up |
2063 | ; as 0 when scaled to 8 bits. To avoid introducing spurious colors into the |
2063 | ; as 0 when scaled to 8 bits. To avoid introducing spurious colors into the |
2064 | ; output change for this too. |
2064 | ; output change for this too. |
2065 | 2065 | ||
2066 | mov eax,[alpha] |
2066 | mov eax,[alpha] |
2067 | cmp [component],eax |
2067 | cmp [component],eax |
2068 | jge @f |
2068 | jge @f |
2069 | cmp eax,128 |
2069 | cmp eax,128 |
2070 | jge .end0 |
2070 | jge .end0 |
2071 | @@: ;if (..>=.. || ..<..) |
2071 | @@: ;if (..>=.. || ..<..) |
2072 | mov eax,255 |
2072 | mov eax,255 |
2073 | jmp .end_f |
2073 | jmp .end_f |
2074 | ; component |
2074 | ; component |
2075 | ; component*reciprocal is less than 2^31. |
2075 | ; component*reciprocal is less than 2^31. |
2076 | 2076 | ||
2077 | .end0: ;else if (component > 0) |
2077 | .end0: ;else if (component > 0) |
2078 | cmp dword[component],0 |
2078 | cmp dword[component],0 |
2079 | jle .end1 |
2079 | jle .end1 |
2080 | ; The test is that alpha/257 (rounded) is less than 255, the first value |
2080 | ; The test is that alpha/257 (rounded) is less than 255, the first value |
2081 | ; that becomes 255 is 65407. |
2081 | ; that becomes 255 is 65407. |
2082 | ; NOTE: this must agree with the PNG_DIV257 macro (which must, therefore, |
2082 | ; NOTE: this must agree with the PNG_DIV257 macro (which must, therefore, |
2083 | ; be exact!) [Could also test reciprocal != 0] |
2083 | ; be exact!) [Could also test reciprocal != 0] |
2084 | 2084 | ||
2085 | ; if (alpha < 65407) |
2085 | ; if (alpha < 65407) |
2086 | ; { |
2086 | ; { |
2087 | ; component *= reciprocal; |
2087 | ; component *= reciprocal; |
2088 | ; component += 64; /* round to nearest */ |
2088 | ; component += 64; /* round to nearest */ |
2089 | ; component >>= 7; |
2089 | ; component >>= 7; |
2090 | ; } |
2090 | ; } |
2091 | 2091 | ||
2092 | ; else |
2092 | ; else |
2093 | ; component *= 255; |
2093 | ; component *= 255; |
2094 | 2094 | ||
2095 | ; Convert the component to sRGB. |
2095 | ; Convert the component to sRGB. |
2096 | PNG_sRGB_FROM_LINEAR [component] |
2096 | PNG_sRGB_FROM_LINEAR [component] |
2097 | and eax,0xff |
2097 | and eax,0xff |
2098 | jmp .end_f |
2098 | jmp .end_f |
2099 | .end1: ;else |
2099 | .end1: ;else |
2100 | xor eax,eax |
2100 | xor eax,eax |
2101 | .end_f: |
2101 | .end_f: |
2102 | ret |
2102 | ret |
2103 | endp |
2103 | endp |
2104 | 2104 | ||
2105 | ;int (voidp argument) |
2105 | ;int (voidp argument) |
2106 | align 4 |
2106 | align 4 |
2107 | proc png_write_image_8bit uses ebx ecx edx edi esi, argument:dword |
2107 | proc png_write_image_8bit uses ebx ecx edx edi esi, argument:dword |
2108 | locals |
2108 | locals |
2109 | display dd ? ;png_image_write_control* ;= argument |
2109 | display dd ? ;png_image_write_control* ;= argument |
2110 | image dd ? ;png_imagep ;= display->image |
2110 | image dd ? ;png_imagep ;= display->image |
2111 | png_ptr dd ? ;png_structrp ;= image->opaque->png_ptr |
2111 | png_ptr dd ? ;png_structrp ;= image->opaque->png_ptr |
2112 | input_row dd ? ;const_uint_16p ;= display->first_row |
2112 | input_row dd ? ;const_uint_16p ;= display->first_row |
2113 | output_row dd ? ;uint_16p ;= display->local_row |
2113 | output_row dd ? ;uint_16p ;= display->local_row |
2114 | row_end dd ? ;uint_16p |
2114 | row_end dd ? ;uint_16p |
2115 | channels dd ? ;const int ;= (image->format & PNG_FORMAT_FLAG_COLOR) != 0 ? 3 : 1; |
2115 | channels dd ? ;const int ;= (image->format & PNG_FORMAT_FLAG_COLOR) != 0 ? 3 : 1; |
2116 | aindex dd 0 ;int ;= 0 |
2116 | aindex dd 0 ;int ;= 0 |
2117 | y dd ? ;uint_32 ;= image->height |
2117 | y dd ? ;uint_32 ;= image->height |
2118 | component dd ? ;uint_32 |
2118 | component dd ? ;uint_32 |
2119 | endl |
2119 | endl |
2120 | mov ebx,[argument] |
2120 | mov ebx,[argument] |
2121 | mov [display],ebx |
2121 | mov [display],ebx |
2122 | mov edx,[ebx+png_image_write_control.image] |
2122 | mov edx,[ebx+png_image_write_control.image] |
2123 | mov [image],edx |
2123 | mov [image],edx |
2124 | mov ecx,[edx+png_image.opaque] |
2124 | mov ecx,[edx+png_image.opaque] |
2125 | mov ecx,[ecx+png_control.png_ptr] |
2125 | mov ecx,[ecx+png_control.png_ptr] |
2126 | mov [png_ptr],ecx |
2126 | mov [png_ptr],ecx |
2127 | mov ecx,[ebx+png_image_write_control.first_row] |
2127 | mov ecx,[ebx+png_image_write_control.first_row] |
2128 | mov [input_row],ecx |
2128 | mov [input_row],ecx |
2129 | mov ecx,[ebx+png_image_write_control.local_row] |
2129 | mov ecx,[ebx+png_image_write_control.local_row] |
2130 | mov [output_row],ecx |
2130 | mov [output_row],ecx |
2131 | 2131 | ||
2132 | mov ecx,1 |
2132 | mov ecx,1 |
2133 | mov eax,[edx+png_image.format] |
2133 | mov eax,[edx+png_image.format] |
2134 | and eax,PNG_FORMAT_FLAG_COLOR |
2134 | and eax,PNG_FORMAT_FLAG_COLOR |
2135 | jz @f |
2135 | jz @f |
2136 | mov ecx,3 |
2136 | mov ecx,3 |
2137 | @@: |
2137 | @@: |
2138 | mov [channels],ecx |
2138 | mov [channels],ecx |
2139 | mov eax,[edx+png_image.height] |
2139 | mov eax,[edx+png_image.height] |
2140 | mov [y],eax |
2140 | mov [y],eax |
2141 | 2141 | ||
2142 | mov eax,[edx+png_image.format] |
2142 | mov eax,[edx+png_image.format] |
2143 | and eax,PNG_FORMAT_FLAG_ALPHA |
2143 | and eax,PNG_FORMAT_FLAG_ALPHA |
2144 | jz .end0 ;if (..!=0) |
2144 | jz .end0 ;if (..!=0) |
2145 | ; bytep row_end; |
2145 | ; bytep row_end; |
2146 | ; int aindex; |
2146 | ; int aindex; |
2147 | 2147 | ||
2148 | if PNG_SIMPLIFIED_WRITE_AFIRST_SUPPORTED eq 1 |
2148 | if PNG_SIMPLIFIED_WRITE_AFIRST_SUPPORTED eq 1 |
2149 | ; if ((image->format & PNG_FORMAT_FLAG_AFIRST) != 0) |
2149 | ; if ((image->format & PNG_FORMAT_FLAG_AFIRST) != 0) |
2150 | ; { |
2150 | ; { |
2151 | ; aindex = -1; |
2151 | ; aindex = -1; |
2152 | ; ++input_row; /* To point to the first component */ |
2152 | ; ++input_row; /* To point to the first component */ |
2153 | ; ++output_row; |
2153 | ; ++output_row; |
2154 | ; } |
2154 | ; } |
2155 | 2155 | ||
2156 | ; else |
2156 | ; else |
2157 | end if |
2157 | end if |
2158 | ; aindex = channels; |
2158 | ; aindex = channels; |
2159 | 2159 | ||
2160 | ; Use row_end in place of a loop counter: |
2160 | ; Use row_end in place of a loop counter: |
2161 | ; row_end = output_row + image->width * (channels+1); |
2161 | ; row_end = output_row + image->width * (channels+1); |
2162 | 2162 | ||
2163 | ; while (y-- > 0) |
2163 | ; while (y-- > 0) |
2164 | ; { |
2164 | ; { |
2165 | ; const_uint_16p in_ptr = input_row; |
2165 | ; const_uint_16p in_ptr = input_row; |
2166 | ; bytep out_ptr = output_row; |
2166 | ; bytep out_ptr = output_row; |
2167 | 2167 | ||
2168 | ; while (out_ptr < row_end) |
2168 | ; while (out_ptr < row_end) |
2169 | ; { |
2169 | ; { |
2170 | ; uint_16 alpha = in_ptr[aindex]; |
2170 | ; uint_16 alpha = in_ptr[aindex]; |
2171 | ; byte alphabyte = (byte)PNG_DIV257(alpha); |
2171 | ; byte alphabyte = (byte)PNG_DIV257(alpha); |
2172 | ; uint_32 reciprocal = 0; |
2172 | ; uint_32 reciprocal = 0; |
2173 | ; int c; |
2173 | ; int c; |
2174 | 2174 | ||
2175 | ; Scale and write the alpha channel. |
2175 | ; Scale and write the alpha channel. |
2176 | ; out_ptr[aindex] = alphabyte; |
2176 | ; out_ptr[aindex] = alphabyte; |
2177 | 2177 | ||
2178 | ; if (alphabyte > 0 && alphabyte < 255) |
2178 | ; if (alphabyte > 0 && alphabyte < 255) |
2179 | ; reciprocal = UNP_RECIPROCAL(alpha); |
2179 | ; reciprocal = UNP_RECIPROCAL(alpha); |
2180 | 2180 | ||
2181 | ; c = channels; |
2181 | ; c = channels; |
2182 | ; do /* always at least one channel */ |
2182 | ; do /* always at least one channel */ |
2183 | ; *out_ptr++ = png_unpremultiply(*in_ptr++, alpha, reciprocal); |
2183 | ; *out_ptr++ = png_unpremultiply(*in_ptr++, alpha, reciprocal); |
2184 | ; while (--c > 0); |
2184 | ; while (--c > 0); |
2185 | 2185 | ||
2186 | ; Skip to next component (skip the intervening alpha channel) |
2186 | ; Skip to next component (skip the intervening alpha channel) |
2187 | ; ++in_ptr; |
2187 | ; ++in_ptr; |
2188 | ; ++out_ptr; |
2188 | ; ++out_ptr; |
2189 | ; } /* while out_ptr < row_end */ |
2189 | ; } /* while out_ptr < row_end */ |
2190 | 2190 | ||
2191 | ; png_write_row(png_ptr, display->local_row); |
2191 | ; png_write_row(png_ptr, display->local_row); |
2192 | ; input_row += display->row_bytes/(sizeof (uint_16)); |
2192 | ; input_row += display->row_bytes/(sizeof (uint_16)); |
2193 | ; } /* while y */ |
2193 | ; } /* while y */ |
2194 | jmp .end1 |
2194 | jmp .end1 |
2195 | .end0: ;else |
2195 | .end0: ;else |
2196 | ; No alpha channel, so the row_end really is the end of the row and it |
2196 | ; No alpha channel, so the row_end really is the end of the row and it |
2197 | ; is sufficient to loop over the components one by one. |
2197 | ; is sufficient to loop over the components one by one. |
2198 | 2198 | ||
2199 | mov ecx,[edx+png_image.width] |
2199 | mov ecx,[edx+png_image.width] |
2200 | imul ecx,[channels] |
2200 | imul ecx,[channels] |
2201 | add ecx,[output_row] |
2201 | add ecx,[output_row] |
2202 | ;ecx = row_end |
2202 | ;ecx = row_end |
2203 | 2203 | ||
2204 | .cycle2: ;while (y-- > 0) |
2204 | .cycle2: ;while (y-- > 0) |
2205 | cmp dword[y],0 |
2205 | cmp dword[y],0 |
2206 | jle .cycle2end |
2206 | jle .cycle2end |
2207 | mov esi,[input_row] |
2207 | mov esi,[input_row] |
2208 | mov edi,[output_row] |
2208 | mov edi,[output_row] |
2209 | ;esi = in_ptr |
2209 | ;esi = in_ptr |
2210 | ;edi = out_ptr |
2210 | ;edi = out_ptr |
2211 | 2211 | ||
2212 | .cycle3: ;while (..<..) |
2212 | .cycle3: ;while (..<..) |
2213 | cmp edi,ecx |
2213 | cmp edi,ecx |
2214 | jge .cycle3end |
2214 | jge .cycle3end |
2215 | xor eax,eax |
2215 | xor eax,eax |
2216 | lodsw |
2216 | lodsw |
2217 | 2217 | ||
2218 | imul eax,255 |
2218 | imul eax,255 |
2219 | mov [component],eax |
2219 | mov [component],eax |
2220 | PNG_sRGB_FROM_LINEAR [component] |
2220 | PNG_sRGB_FROM_LINEAR [component] |
2221 | stosb |
2221 | stosb |
2222 | jmp .cycle3 |
2222 | jmp .cycle3 |
2223 | align 4 |
2223 | align 4 |
2224 | .cycle3end: |
2224 | .cycle3end: |
2225 | 2225 | ||
2226 | stdcall png_write_row, [png_ptr], [output_row] |
2226 | stdcall png_write_row, [png_ptr], [output_row] |
2227 | mov eax,[ebx+png_image_write_control.row_bytes] |
2227 | mov eax,[ebx+png_image_write_control.row_bytes] |
2228 | shr eax,1 ;sizeof.uint_16 |
2228 | shr eax,1 ;sizeof.uint_16 |
2229 | add [input_row],eax |
2229 | add [input_row],eax |
2230 | dec dword[y] |
2230 | dec dword[y] |
2231 | jmp .cycle2 |
2231 | jmp .cycle2 |
2232 | align 4 |
2232 | align 4 |
2233 | .cycle2end: |
2233 | .cycle2end: |
2234 | .end1: |
2234 | .end1: |
2235 | 2235 | ||
2236 | xor eax,eax |
2236 | xor eax,eax |
2237 | inc eax |
2237 | inc eax |
2238 | ret |
2238 | ret |
2239 | endp |
2239 | endp |
2240 | 2240 | ||
2241 | ;void (png_image_write_control *display) |
2241 | ;void (png_image_write_control *display) |
2242 | align 4 |
2242 | align 4 |
2243 | proc png_image_set_PLTE, display:dword |
2243 | proc png_image_set_PLTE, display:dword |
2244 | locals |
2244 | locals |
2245 | image dd ? ;png_imagep ;= display->image |
2245 | image dd ? ;png_imagep ;= display->image |
2246 | cmap dd ? ;void * ;= display->colormap |
2246 | cmap dd ? ;void * ;= display->colormap |
2247 | entries dd ? ;int |
2247 | entries dd ? ;int |
2248 | 2248 | ||
2249 | ; NOTE: the caller must check for cmap != NULL and entries != 0 |
2249 | ; NOTE: the caller must check for cmap != NULL and entries != 0 |
2250 | format dd ? ;uint_32 ;= image->format |
2250 | format dd ? ;uint_32 ;= image->format |
2251 | channels dd ? ;int |
2251 | channels dd ? ;int |
2252 | afirst dd 0 |
2252 | afirst dd 0 |
2253 | bgr dd 0 |
2253 | bgr dd 0 |
2254 | num_trans dd 0 |
2254 | num_trans dd 0 |
2255 | palette rb 256*sizeof.png_color |
2255 | palette rb 256*sizeof.png_color |
2256 | tRNS rb 256 ;byte[] |
2256 | tRNS rb 256 ;byte[] |
2257 | endl |
2257 | endl |
2258 | pushad |
2258 | pushad |
2259 | mov edx,[display] |
2259 | mov edx,[display] |
2260 | mov ebx,[edx+png_image_write_control.image] |
2260 | mov ebx,[edx+png_image_write_control.image] |
2261 | mov [image],ebx |
2261 | mov [image],ebx |
2262 | mov eax,[edx+png_image_write_control.colormap] |
2262 | mov eax,[edx+png_image_write_control.colormap] |
2263 | mov [cmap],eax |
2263 | mov [cmap],eax |
2264 | mov eax,[ebx+png_image.colormap_entries] |
2264 | mov eax,[ebx+png_image.colormap_entries] |
2265 | cmp eax,256 |
2265 | cmp eax,256 |
2266 | jle @f |
2266 | jle @f |
2267 | mov eax,256 |
2267 | mov eax,256 |
2268 | @@: |
2268 | @@: |
2269 | mov [entries],eax |
2269 | mov [entries],eax |
2270 | mov ecx,[ebx+png_image.format] |
2270 | mov ecx,[ebx+png_image.format] |
2271 | mov [format],ecx |
2271 | mov [format],ecx |
2272 | PNG_IMAGE_SAMPLE_CHANNELS ecx |
2272 | PNG_IMAGE_SAMPLE_CHANNELS ecx |
2273 | mov [channels],eax |
2273 | mov [channels],eax |
2274 | 2274 | ||
2275 | if (PNG_FORMAT_BGR_SUPPORTED eq 1) & (PNG_SIMPLIFIED_WRITE_AFIRST_SUPPORTED eq 1) |
2275 | if (PNG_FORMAT_BGR_SUPPORTED eq 1) & (PNG_SIMPLIFIED_WRITE_AFIRST_SUPPORTED eq 1) |
2276 | mov eax,ecx |
2276 | mov eax,ecx |
2277 | and eax,PNG_FORMAT_FLAG_AFIRST |
2277 | and eax,PNG_FORMAT_FLAG_AFIRST |
2278 | jz @f |
2278 | jz @f |
2279 | mov eax,ecx |
2279 | mov eax,ecx |
2280 | and eax,PNG_FORMAT_FLAG_ALPHA |
2280 | and eax,PNG_FORMAT_FLAG_ALPHA |
2281 | jz @f |
2281 | jz @f |
2282 | mov dword[afirst],-1 |
2282 | mov dword[afirst],-1 |
2283 | @@: |
2283 | @@: |
2284 | end if |
2284 | end if |
2285 | 2285 | ||
2286 | if PNG_FORMAT_BGR_SUPPORTED eq 1 |
2286 | if PNG_FORMAT_BGR_SUPPORTED eq 1 |
2287 | mov eax,ecx |
2287 | mov eax,ecx |
2288 | and eax,PNG_FORMAT_FLAG_BGR |
2288 | and eax,PNG_FORMAT_FLAG_BGR |
2289 | jz @f |
2289 | jz @f |
2290 | mov dword[bgr],2 |
2290 | mov dword[bgr],2 |
2291 | @@: |
2291 | @@: |
2292 | end if |
2292 | end if |
2293 | 2293 | ||
2294 | ; int i; |
2294 | ; int i; |
2295 | 2295 | ||
2296 | xor eax,eax |
2296 | xor eax,eax |
2297 | mov ecx,(256*sizeof.png_color)/4 |
2297 | mov ecx,(256*sizeof.png_color)/4 |
2298 | mov edi,ebp |
2298 | mov edi,ebp |
2299 | sub edi,256+256*sizeof.png_color |
2299 | sub edi,256+256*sizeof.png_color |
2300 | rep stosd ;memset(palette, 0, ... |
2300 | rep stosd ;memset(palette, 0, ... |
2301 | not eax |
2301 | not eax |
2302 | mov ecx,256/4 |
2302 | mov ecx,256/4 |
2303 | ;;mov edi,ebp ;if 'tRNS' after 'palette' this code can be comment |
2303 | ;;mov edi,ebp ;if 'tRNS' after 'palette' this code can be comment |
2304 | ;;sub edi,256 |
2304 | ;;sub edi,256 |
2305 | rep stosd ;memset(tRNS, 255, ... |
2305 | rep stosd ;memset(tRNS, 255, ... |
2306 | 2306 | ||
2307 | 2307 | ||
2308 | ; for (i=num_trans=0; i |
2308 | ; for (i=num_trans=0; i |
2309 | ; { |
2309 | ; { |
2310 | ; This gets automatically converted to sRGB with reversal of the |
2310 | ; This gets automatically converted to sRGB with reversal of the |
2311 | ; pre-multiplication if the color-map has an alpha channel. |
2311 | ; pre-multiplication if the color-map has an alpha channel. |
2312 | 2312 | ||
2313 | ; if ((format & PNG_FORMAT_FLAG_LINEAR) != 0) |
2313 | ; if ((format & PNG_FORMAT_FLAG_LINEAR) != 0) |
2314 | ; { |
2314 | ; { |
2315 | ; png_const_uint_16p entry = cmap; |
2315 | ; png_const_uint_16p entry = cmap; |
2316 | 2316 | ||
2317 | ; entry += i * channels; |
2317 | ; entry += i * channels; |
2318 | 2318 | ||
2319 | ; if ((channels & 1) != 0) /* no alpha */ |
2319 | ; if ((channels & 1) != 0) /* no alpha */ |
2320 | ; { |
2320 | ; { |
2321 | ; if (channels >= 3) /* RGB */ |
2321 | ; if (channels >= 3) /* RGB */ |
2322 | ; { |
2322 | ; { |
2323 | ; palette[i].blue = (byte)PNG_sRGB_FROM_LINEAR(255 * |
2323 | ; palette[i].blue = (byte)PNG_sRGB_FROM_LINEAR(255 * |
2324 | ; entry[(2 ^ bgr)]); |
2324 | ; entry[(2 ^ bgr)]); |
2325 | ; palette[i].green = (byte)PNG_sRGB_FROM_LINEAR(255 * |
2325 | ; palette[i].green = (byte)PNG_sRGB_FROM_LINEAR(255 * |
2326 | ; entry[1]); |
2326 | ; entry[1]); |
2327 | ; palette[i].red = (byte)PNG_sRGB_FROM_LINEAR(255 * |
2327 | ; palette[i].red = (byte)PNG_sRGB_FROM_LINEAR(255 * |
2328 | ; entry[bgr]); |
2328 | ; entry[bgr]); |
2329 | ; } |
2329 | ; } |
2330 | 2330 | ||
2331 | ; else /* Gray */ |
2331 | ; else /* Gray */ |
2332 | ; palette[i].blue = palette[i].red = palette[i].green = |
2332 | ; palette[i].blue = palette[i].red = palette[i].green = |
2333 | ; (byte)PNG_sRGB_FROM_LINEAR(255 * *entry); |
2333 | ; (byte)PNG_sRGB_FROM_LINEAR(255 * *entry); |
2334 | ; } |
2334 | ; } |
2335 | 2335 | ||
2336 | ; else /* alpha */ |
2336 | ; else /* alpha */ |
2337 | ; { |
2337 | ; { |
2338 | ; uint_16 alpha = entry[afirst ? 0 : channels-1]; |
2338 | ; uint_16 alpha = entry[afirst ? 0 : channels-1]; |
2339 | ; byte alphabyte = (byte)PNG_DIV257(alpha); |
2339 | ; byte alphabyte = (byte)PNG_DIV257(alpha); |
2340 | ; uint_32 reciprocal = 0; |
2340 | ; uint_32 reciprocal = 0; |
2341 | 2341 | ||
2342 | ; Calculate a reciprocal, as in the png_write_image_8bit code above |
2342 | ; Calculate a reciprocal, as in the png_write_image_8bit code above |
2343 | ; this is designed to produce a value scaled to 255*65535 when |
2343 | ; this is designed to produce a value scaled to 255*65535 when |
2344 | ; divided by 128 (i.e. asr 7). |
2344 | ; divided by 128 (i.e. asr 7). |
2345 | 2345 | ||
2346 | ; if (alphabyte > 0 && alphabyte < 255) |
2346 | ; if (alphabyte > 0 && alphabyte < 255) |
2347 | ; reciprocal = (((0xffff*0xff)<<7)+(alpha>>1))/alpha; |
2347 | ; reciprocal = (((0xffff*0xff)<<7)+(alpha>>1))/alpha; |
2348 | 2348 | ||
2349 | ; tRNS[i] = alphabyte; |
2349 | ; tRNS[i] = alphabyte; |
2350 | ; if (alphabyte < 255) |
2350 | ; if (alphabyte < 255) |
2351 | ; num_trans = i+1; |
2351 | ; num_trans = i+1; |
2352 | 2352 | ||
2353 | ; if (channels >= 3) /* RGB */ |
2353 | ; if (channels >= 3) /* RGB */ |
2354 | ; { |
2354 | ; { |
2355 | ; palette[i].blue = png_unpremultiply(entry[afirst + (2 ^ bgr)], |
2355 | ; palette[i].blue = png_unpremultiply(entry[afirst + (2 ^ bgr)], |
2356 | ; alpha, reciprocal); |
2356 | ; alpha, reciprocal); |
2357 | ; palette[i].green = png_unpremultiply(entry[afirst + 1], alpha, |
2357 | ; palette[i].green = png_unpremultiply(entry[afirst + 1], alpha, |
2358 | ; reciprocal); |
2358 | ; reciprocal); |
2359 | ; palette[i].red = png_unpremultiply(entry[afirst + bgr], alpha, |
2359 | ; palette[i].red = png_unpremultiply(entry[afirst + bgr], alpha, |
2360 | ; reciprocal); |
2360 | ; reciprocal); |
2361 | ; } |
2361 | ; } |
2362 | 2362 | ||
2363 | ; else /* gray */ |
2363 | ; else /* gray */ |
2364 | ; palette[i].blue = palette[i].red = palette[i].green = |
2364 | ; palette[i].blue = palette[i].red = palette[i].green = |
2365 | ; png_unpremultiply(entry[afirst], alpha, reciprocal); |
2365 | ; png_unpremultiply(entry[afirst], alpha, reciprocal); |
2366 | ; } |
2366 | ; } |
2367 | ; } |
2367 | ; } |
2368 | 2368 | ||
2369 | ; else /* Color-map has sRGB values */ |
2369 | ; else /* Color-map has sRGB values */ |
2370 | ; { |
2370 | ; { |
2371 | ; bytep entry = cmap; |
2371 | ; bytep entry = cmap; |
2372 | 2372 | ||
2373 | ; entry += i * channels; |
2373 | ; entry += i * channels; |
2374 | 2374 | ||
2375 | ; switch (channels) |
2375 | ; switch (channels) |
2376 | ; { |
2376 | ; { |
2377 | ; case 4: |
2377 | ; case 4: |
2378 | ; tRNS[i] = entry[afirst ? 0 : 3]; |
2378 | ; tRNS[i] = entry[afirst ? 0 : 3]; |
2379 | ; if (tRNS[i] < 255) |
2379 | ; if (tRNS[i] < 255) |
2380 | ; num_trans = i+1; |
2380 | ; num_trans = i+1; |
2381 | ; /* FALL THROUGH */ |
2381 | ; /* FALL THROUGH */ |
2382 | ; case 3: |
2382 | ; case 3: |
2383 | ; palette[i].blue = entry[afirst + (2 ^ bgr)]; |
2383 | ; palette[i].blue = entry[afirst + (2 ^ bgr)]; |
2384 | ; palette[i].green = entry[afirst + 1]; |
2384 | ; palette[i].green = entry[afirst + 1]; |
2385 | ; palette[i].red = entry[afirst + bgr]; |
2385 | ; palette[i].red = entry[afirst + bgr]; |
2386 | ; break; |
2386 | ; break; |
2387 | 2387 | ||
2388 | ; case 2: |
2388 | ; case 2: |
2389 | ; tRNS[i] = entry[1 ^ afirst]; |
2389 | ; tRNS[i] = entry[1 ^ afirst]; |
2390 | ; if (tRNS[i] < 255) |
2390 | ; if (tRNS[i] < 255) |
2391 | ; num_trans = i+1; |
2391 | ; num_trans = i+1; |
2392 | ; /* FALL THROUGH */ |
2392 | ; /* FALL THROUGH */ |
2393 | ; case 1: |
2393 | ; case 1: |
2394 | ; palette[i].blue = palette[i].red = palette[i].green = |
2394 | ; palette[i].blue = palette[i].red = palette[i].green = |
2395 | ; entry[afirst]; |
2395 | ; entry[afirst]; |
2396 | ; break; |
2396 | ; break; |
2397 | 2397 | ||
2398 | ; default: |
2398 | ; default: |
2399 | ; break; |
2399 | ; break; |
2400 | ; } |
2400 | ; } |
2401 | ; } |
2401 | ; } |
2402 | ; } |
2402 | ; } |
2403 | 2403 | ||
2404 | mov ecx,[ebx+png_image.opaque] |
2404 | mov ecx,[ebx+png_image.opaque] |
2405 | mov eax,ebp |
2405 | mov eax,ebp |
2406 | sub eax,256+256*sizeof.png_color |
2406 | sub eax,256+256*sizeof.png_color |
2407 | stdcall png_set_PLTE, [ecx+png_control.png_ptr], [ecx+png_control.info_ptr], eax, [entries] |
2407 | stdcall png_set_PLTE, [ecx+png_control.png_ptr], [ecx+png_control.info_ptr], eax, [entries] |
2408 | 2408 | ||
2409 | cmp dword[num_trans],0 |
2409 | cmp dword[num_trans],0 |
2410 | jle @f ;if (..>0) |
2410 | jle @f ;if (..>0) |
2411 | mov eax,ebp |
2411 | mov eax,ebp |
2412 | sub eax,256 |
2412 | sub eax,256 |
2413 | stdcall png_set_tRNS, [ecx+png_control.png_ptr], [ecx+png_control.info_ptr], eax, [num_trans], 0 |
2413 | stdcall png_set_tRNS, [ecx+png_control.png_ptr], [ecx+png_control.info_ptr], eax, [num_trans], 0 |
2414 | @@: |
2414 | @@: |
2415 | 2415 | ||
2416 | mov eax,[entries] |
2416 | mov eax,[entries] |
2417 | mov [ebx+png_image.colormap_entries],eax |
2417 | mov [ebx+png_image.colormap_entries],eax |
2418 | popad |
2418 | popad |
2419 | ret |
2419 | ret |
2420 | endp |
2420 | endp |
2421 | 2421 | ||
2422 | ;int (voidp argument) |
2422 | ;int (voidp argument) |
2423 | align 4 |
2423 | align 4 |
2424 | proc png_image_write_main uses ebx ecx edx esi edi, argument:dword |
2424 | proc png_image_write_main uses ebx ecx edx esi edi, argument:dword |
2425 | locals |
2425 | locals |
2426 | display dd ? ;= png_image_write_control * = argument |
2426 | display dd ? ;= png_image_write_control * = argument |
2427 | image dd ? ;= display->image |
2427 | image dd ? ;= display->image |
2428 | png_ptr dd ? ;= image->opaque->png_ptr |
2428 | png_ptr dd ? ;= image->opaque->png_ptr |
2429 | info_ptr dd ? ;= image->opaque->info_ptr |
2429 | info_ptr dd ? ;= image->opaque->info_ptr |
2430 | format dd ? ;= image->format |
2430 | format dd ? ;= image->format |
2431 | 2431 | ||
2432 | colormap dd ? |
2432 | colormap dd ? |
2433 | linear dd ? |
2433 | linear dd ? |
2434 | alpha dd ? |
2434 | alpha dd ? |
2435 | write_16bit dd ? ;= linear && !colormap && (display->convert_to_8bit == 0) |
2435 | write_16bit dd ? ;= linear && !colormap && (display->convert_to_8bit == 0) |
2436 | endl |
2436 | endl |
2437 | mov edx,[argument] |
2437 | mov edx,[argument] |
2438 | mov [display],edx |
2438 | mov [display],edx |
2439 | mov ebx,[edx+png_image_write_control.image] |
2439 | mov ebx,[edx+png_image_write_control.image] |
2440 | mov [image],ebx |
2440 | mov [image],ebx |
2441 | mov ecx,[ebx+png_image.format] |
2441 | mov ecx,[ebx+png_image.format] |
2442 | mov [format],ecx |
2442 | mov [format],ecx |
2443 | mov eax,[ebx+png_image.opaque] |
2443 | mov eax,[ebx+png_image.opaque] |
2444 | mov edi,[eax+png_control.png_ptr] |
2444 | mov edi,[eax+png_control.png_ptr] |
2445 | mov [png_ptr],edi |
2445 | mov [png_ptr],edi |
2446 | mov esi,[eax+png_control.info_ptr] |
2446 | mov esi,[eax+png_control.info_ptr] |
2447 | mov [info_ptr],esi |
2447 | mov [info_ptr],esi |
2448 | 2448 | ||
2449 | ; The following four ints are actually booleans |
2449 | ; The following four ints are actually booleans |
2450 | and ecx,PNG_FORMAT_FLAG_COLORMAP |
2450 | and ecx,PNG_FORMAT_FLAG_COLORMAP |
2451 | mov [colormap],ecx |
2451 | mov [colormap],ecx |
2452 | not ecx |
2452 | not ecx |
2453 | mov eax,[format] |
2453 | mov eax,[format] |
2454 | and eax,PNG_FORMAT_FLAG_LINEAR |
2454 | and eax,PNG_FORMAT_FLAG_LINEAR |
2455 | mov [linear],eax |
2455 | mov [linear],eax |
2456 | mov eax,[format] |
2456 | mov eax,[format] |
2457 | and eax,ecx |
2457 | and eax,ecx |
2458 | and eax,PNG_FORMAT_FLAG_ALPHA |
2458 | and eax,PNG_FORMAT_FLAG_ALPHA |
2459 | and eax,ecx |
2459 | and eax,ecx |
2460 | mov [alpha],eax |
2460 | mov [alpha],eax |
2461 | xor eax,eax ;false |
2461 | xor eax,eax ;false |
2462 | cmp dword[edx+png_image_write_control.convert_to_8bit],0 |
2462 | cmp dword[edx+png_image_write_control.convert_to_8bit],0 |
2463 | jne @f |
2463 | jne @f |
2464 | not eax ;true |
2464 | not eax ;true |
2465 | @@: |
2465 | @@: |
2466 | and eax,[linear] |
2466 | and eax,[linear] |
2467 | and eax,ecx |
2467 | and eax,ecx |
2468 | mov [write_16bit],eax |
2468 | mov [write_16bit],eax |
2469 | 2469 | ||
2470 | if PNG_BENIGN_ERRORS_SUPPORTED eq 1 |
2470 | if PNG_BENIGN_ERRORS_SUPPORTED eq 1 |
2471 | ; Make sure we error out on any bad situation |
2471 | ; Make sure we error out on any bad situation |
2472 | stdcall png_set_benign_errors, edi, 0 ;error |
2472 | stdcall png_set_benign_errors, edi, 0 ;error |
2473 | end if |
2473 | end if |
2474 | 2474 | ||
2475 | ; Default the 'row_stride' parameter if required, also check the row stride |
2475 | ; Default the 'row_stride' parameter if required, also check the row stride |
2476 | ; and total image size to ensure that they are within the system limits. |
2476 | ; and total image size to ensure that they are within the system limits. |
2477 | 2477 | ||
2478 | PNG_IMAGE_PIXEL_CHANNELS [ebx+png_image.format] |
2478 | PNG_IMAGE_PIXEL_CHANNELS [ebx+png_image.format] |
2479 | ;eax = channels |
2479 | ;eax = channels |
2480 | 2480 | ||
2481 | push edx |
2481 | push edx |
2482 | mov ecx,eax |
2482 | mov ecx,eax |
2483 | mov eax,0x7FFFFFFF |
2483 | mov eax,0x7FFFFFFF |
2484 | xor edx,edx |
2484 | xor edx,edx |
2485 | div ecx |
2485 | div ecx |
2486 | pop edx |
2486 | pop edx |
2487 | cmp [ebx+png_image.width],eax |
2487 | cmp [ebx+png_image.width],eax |
2488 | jg .end0 ;if (..<=..) ;no overflow |
2488 | jg .end0 ;if (..<=..) ;no overflow |
2489 | imul ecx,[ebx+png_image.width] |
2489 | imul ecx,[ebx+png_image.width] |
2490 | 2490 | ||
2491 | cmp dword[edx+png_image_write_control.row_stride],0 |
2491 | cmp dword[edx+png_image_write_control.row_stride],0 |
2492 | jne @f ;if (..==0) |
2492 | jne @f ;if (..==0) |
2493 | mov [edx+png_image_write_control.row_stride],ecx |
2493 | mov [edx+png_image_write_control.row_stride],ecx |
2494 | @@: |
2494 | @@: |
2495 | mov eax,[edx+png_image_write_control.row_stride] |
2495 | mov eax,[edx+png_image_write_control.row_stride] |
2496 | cmp eax,0 |
2496 | cmp eax,0 |
2497 | jge .end2 ;if (..<0) |
2497 | jge .end2 ;if (..<0) |
2498 | neg eax |
2498 | neg eax |
2499 | inc eax |
2499 | inc eax |
2500 | .end2: |
2500 | .end2: |
2501 | 2501 | ||
2502 | cmp eax,ecx |
2502 | cmp eax,ecx |
2503 | jl .end3 ;if (..>=..) |
2503 | jl .end3 ;if (..>=..) |
2504 | ; Now check for overflow of the image buffer calculation; this |
2504 | ; Now check for overflow of the image buffer calculation; this |
2505 | ; limits the whole image size to 32 bits for API compatibility with |
2505 | ; limits the whole image size to 32 bits for API compatibility with |
2506 | ; the current, 32-bit, PNG_IMAGE_BUFFER_SIZE macro. |
2506 | ; the current, 32-bit, PNG_IMAGE_BUFFER_SIZE macro. |
2507 | 2507 | ||
2508 | push edx |
2508 | push edx |
2509 | mov eax,0xFFFFFFFF |
2509 | mov eax,0xFFFFFFFF |
2510 | xor edx,edx |
2510 | xor edx,edx |
2511 | div ecx |
2511 | div ecx |
2512 | pop edx |
2512 | pop edx |
2513 | cmp [ebx+png_image.height],eax |
2513 | cmp [ebx+png_image.height],eax |
2514 | jle @f ;if (..>..) |
2514 | jle @f ;if (..>..) |
2515 | mov eax,[ebx+png_image.opaque] |
2515 | mov eax,[ebx+png_image.opaque] |
2516 | mov eax,[eax+png_control.png_ptr] |
2516 | mov eax,[eax+png_control.png_ptr] |
2517 | png_error eax, 'memory image too large' |
2517 | png_error eax, 'memory image too large' |
2518 | @@: |
2518 | @@: |
2519 | jmp .end1 |
2519 | jmp .end1 |
2520 | .end3: ;else |
2520 | .end3: ;else |
2521 | mov eax,[ebx+png_image.opaque] |
2521 | mov eax,[ebx+png_image.opaque] |
2522 | mov eax,[eax+png_control.png_ptr] |
2522 | mov eax,[eax+png_control.png_ptr] |
2523 | png_error eax, 'supplied row stride too small' |
2523 | png_error eax, 'supplied row stride too small' |
2524 | jmp .end1 |
2524 | jmp .end1 |
2525 | .end0: ;else |
2525 | .end0: ;else |
2526 | mov eax,[ebx+png_image.opaque] |
2526 | mov eax,[ebx+png_image.opaque] |
2527 | mov eax,[eax+png_control.png_ptr] |
2527 | mov eax,[eax+png_control.png_ptr] |
2528 | png_error eax, 'image row stride too large' |
2528 | png_error eax, 'image row stride too large' |
2529 | .end1: |
2529 | .end1: |
2530 | 2530 | ||
2531 | ; Set the required transforms then write the rows in the correct order. |
2531 | ; Set the required transforms then write the rows in the correct order. |
2532 | mov eax,[format] |
2532 | mov eax,[format] |
2533 | and eax,PNG_FORMAT_FLAG_COLORMAP |
2533 | and eax,PNG_FORMAT_FLAG_COLORMAP |
2534 | jz .end4 ;if (..!=0) |
2534 | jz .end4 ;if (..!=0) |
2535 | cmp dword[edx+png_image_write_control.colormap],0 |
2535 | cmp dword[edx+png_image_write_control.colormap],0 |
2536 | je .end6 |
2536 | je .end6 |
2537 | mov eax,[ebx+png_image.colormap_entries] |
2537 | mov eax,[ebx+png_image.colormap_entries] |
2538 | cmp eax,0 |
2538 | cmp eax,0 |
2539 | jle .end6 ;if (..!=0 && ..>0) |
2539 | jle .end6 ;if (..!=0 && ..>0) |
2540 | ;eax = entries |
2540 | ;eax = entries |
2541 | xor ecx,ecx |
2541 | xor ecx,ecx |
2542 | inc ecx ;=1 |
2542 | inc ecx ;=1 |
2543 | cmp eax,2 |
2543 | cmp eax,2 |
2544 | jle @f |
2544 | jle @f |
2545 | shl ecx,1 ;=2 |
2545 | shl ecx,1 ;=2 |
2546 | cmp eax,4 |
2546 | cmp eax,4 |
2547 | jle @f |
2547 | jle @f |
2548 | shl ecx,1 ;=4 |
2548 | shl ecx,1 ;=4 |
2549 | cmp eax,16 |
2549 | cmp eax,16 |
2550 | jle @f |
2550 | jle @f |
2551 | shl ecx,1 ;=8 |
2551 | shl ecx,1 ;=8 |
2552 | @@: |
2552 | @@: |
2553 | stdcall png_set_IHDR, edi, esi, [ebx+png_image.width], [ebx+png_image.height],\ |
2553 | stdcall png_set_IHDR, edi, esi, [ebx+png_image.width], [ebx+png_image.height],\ |
2554 | ecx, PNG_COLOR_TYPE_PALETTE, PNG_INTERLACE_NONE,\ |
2554 | ecx, PNG_COLOR_TYPE_PALETTE, PNG_INTERLACE_NONE,\ |
2555 | PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE |
2555 | PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE |
2556 | 2556 | ||
2557 | stdcall png_image_set_PLTE, edx |
2557 | stdcall png_image_set_PLTE, edx |
2558 | jmp .end5 |
2558 | jmp .end5 |
2559 | .end6: ;else |
2559 | .end6: ;else |
2560 | mov eax,[ebx+png_image.opaque] |
2560 | mov eax,[ebx+png_image.opaque] |
2561 | mov eax,[eax+png_control.png_ptr] |
2561 | mov eax,[eax+png_control.png_ptr] |
2562 | png_error eax, 'no color-map for color-mapped image' |
2562 | png_error eax, 'no color-map for color-mapped image' |
2563 | jmp .end5 |
2563 | jmp .end5 |
2564 | .end4: ;else |
2564 | .end4: ;else |
2565 | xor ecx,ecx |
2565 | xor ecx,ecx |
2566 | mov eax,[format] |
2566 | mov eax,[format] |
2567 | and eax,PNG_FORMAT_FLAG_COLOR |
2567 | and eax,PNG_FORMAT_FLAG_COLOR |
2568 | jz @f |
2568 | jz @f |
2569 | or ecx,PNG_COLOR_MASK_COLOR |
2569 | or ecx,PNG_COLOR_MASK_COLOR |
2570 | @@: |
2570 | @@: |
2571 | mov eax,[format] |
2571 | mov eax,[format] |
2572 | and eax,PNG_FORMAT_FLAG_ALPHA |
2572 | and eax,PNG_FORMAT_FLAG_ALPHA |
2573 | jz @f |
2573 | jz @f |
2574 | or ecx,PNG_COLOR_MASK_ALPHA |
2574 | or ecx,PNG_COLOR_MASK_ALPHA |
2575 | @@: |
2575 | @@: |
2576 | mov eax,8 |
2576 | mov eax,8 |
2577 | cmp dword[write_16bit],0 |
2577 | cmp dword[write_16bit],0 |
2578 | je @f |
2578 | je @f |
2579 | mov eax,16 |
2579 | mov eax,16 |
2580 | @@: |
2580 | @@: |
2581 | stdcall png_set_IHDR, edi, esi, [ebx+png_image.width], [ebx+png_image.height],\ |
2581 | stdcall png_set_IHDR, edi, esi, [ebx+png_image.width], [ebx+png_image.height],\ |
2582 | eax, ecx, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE |
2582 | eax, ecx, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE |
2583 | .end5: |
2583 | .end5: |
2584 | 2584 | ||
2585 | ; Counter-intuitively the data transformations must be called *after* |
2585 | ; Counter-intuitively the data transformations must be called *after* |
2586 | ; png_write_info, not before as in the read code, but the 'set' functions |
2586 | ; png_write_info, not before as in the read code, but the 'set' functions |
2587 | ; must still be called before. Just set the color space information, never |
2587 | ; must still be called before. Just set the color space information, never |
2588 | ; write an interlaced image. |
2588 | ; write an interlaced image. |
2589 | 2589 | ||
2590 | cmp dword[write_16bit],0 |
2590 | cmp dword[write_16bit],0 |
2591 | je @f ;if (..!=0) |
2591 | je @f ;if (..!=0) |
2592 | ; The gamma here is 1.0 (linear) and the cHRM chunk matches sRGB. |
2592 | ; The gamma here is 1.0 (linear) and the cHRM chunk matches sRGB. |
2593 | stdcall png_set_gAMA_fixed, edi, esi, PNG_GAMMA_LINEAR |
2593 | stdcall png_set_gAMA_fixed, edi, esi, PNG_GAMMA_LINEAR |
2594 | 2594 | ||
2595 | mov eax,[ebx+png_image.flags] |
2595 | mov eax,[ebx+png_image.flags] |
2596 | and eax,PNG_IMAGE_FLAG_COLORSPACE_NOT_sRGB |
2596 | and eax,PNG_IMAGE_FLAG_COLORSPACE_NOT_sRGB |
2597 | jnz @f ;if (..==0) |
2597 | jnz @f ;if (..==0) |
2598 | stdcall png_set_cHRM_fixed, edi, esi,\ |
2598 | stdcall png_set_cHRM_fixed, edi, esi,\ |
2599 | 31270, 32900,\ ;white |
2599 | 31270, 32900,\ ;white |
2600 | 64000, 33000,\ ;red |
2600 | 64000, 33000,\ ;red |
2601 | 30000, 60000,\ ;green |
2601 | 30000, 60000,\ ;green |
2602 | 15000, 6000 ;blue |
2602 | 15000, 6000 ;blue |
2603 | jmp .end7 |
2603 | jmp .end7 |
2604 | @@: |
2604 | @@: |
2605 | mov eax,[ebx+png_image.flags] |
2605 | mov eax,[ebx+png_image.flags] |
2606 | and eax,PNG_IMAGE_FLAG_COLORSPACE_NOT_sRGB |
2606 | and eax,PNG_IMAGE_FLAG_COLORSPACE_NOT_sRGB |
2607 | jnz @f ;else if (..==0) |
2607 | jnz @f ;else if (..==0) |
2608 | stdcall png_set_sRGB, edi, esi, PNG_sRGB_INTENT_PERCEPTUAL |
2608 | stdcall png_set_sRGB, edi, esi, PNG_sRGB_INTENT_PERCEPTUAL |
2609 | jmp .end7 |
2609 | jmp .end7 |
2610 | @@: ;else |
2610 | @@: ;else |
2611 | ; Else writing an 8-bit file and the *colors* aren't sRGB, but the 8-bit |
2611 | ; Else writing an 8-bit file and the *colors* aren't sRGB, but the 8-bit |
2612 | ; space must still be gamma encoded. |
2612 | ; space must still be gamma encoded. |
2613 | stdcall png_set_gAMA_fixed, edi, esi, PNG_GAMMA_sRGB_INVERSE |
2613 | stdcall png_set_gAMA_fixed, edi, esi, PNG_GAMMA_sRGB_INVERSE |
2614 | .end7: |
2614 | .end7: |
2615 | 2615 | ||
2616 | ; Write the file header. |
2616 | ; Write the file header. |
2617 | stdcall png_write_info, edi, esi |
2617 | stdcall png_write_info, edi, esi |
2618 | 2618 | ||
2619 | ; Now set up the data transformations (*after* the header is written), |
2619 | ; Now set up the data transformations (*after* the header is written), |
2620 | ; remove the handled transformations from the 'format' flags for checking. |
2620 | ; remove the handled transformations from the 'format' flags for checking. |
2621 | 2621 | ||
2622 | ; First check for a little endian system if writing 16-bit files. |
2622 | ; First check for a little endian system if writing 16-bit files. |
2623 | 2623 | ||
2624 | cmp dword[write_16bit],0 |
2624 | cmp dword[write_16bit],0 |
2625 | je @f ;if (..!=0) |
2625 | je @f ;if (..!=0) |
2626 | ; uint_16 le = 0x0001; |
2626 | ; uint_16 le = 0x0001; |
2627 | 2627 | ||
2628 | ; if ((*(bytep) & le) != 0) |
2628 | ; if ((*(bytep) & le) != 0) |
2629 | stdcall png_set_swap, edi |
2629 | stdcall png_set_swap, edi |
2630 | @@: |
2630 | @@: |
2631 | 2631 | ||
2632 | if PNG_SIMPLIFIED_WRITE_BGR_SUPPORTED eq 1 |
2632 | if PNG_SIMPLIFIED_WRITE_BGR_SUPPORTED eq 1 |
2633 | mov eax,[format] |
2633 | mov eax,[format] |
2634 | and eax,PNG_FORMAT_FLAG_BGR |
2634 | and eax,PNG_FORMAT_FLAG_BGR |
2635 | jz .end12 ;if (..!=0) |
2635 | jz .end12 ;if (..!=0) |
2636 | cmp dword[colormap],0 |
2636 | cmp dword[colormap],0 |
2637 | jne @f |
2637 | jne @f |
2638 | mov eax,[format] |
2638 | mov eax,[format] |
2639 | and eax,PNG_FORMAT_FLAG_COLOR |
2639 | and eax,PNG_FORMAT_FLAG_COLOR |
2640 | jz @f ;if (..==0 && ..!=0) |
2640 | jz @f ;if (..==0 && ..!=0) |
2641 | stdcall png_set_bgr, edi |
2641 | stdcall png_set_bgr, edi |
2642 | @@: |
2642 | @@: |
2643 | and dword[format], not PNG_FORMAT_FLAG_BGR |
2643 | and dword[format], not PNG_FORMAT_FLAG_BGR |
2644 | .end12: |
2644 | .end12: |
2645 | end if |
2645 | end if |
2646 | 2646 | ||
2647 | if PNG_SIMPLIFIED_WRITE_AFIRST_SUPPORTED eq 1 |
2647 | if PNG_SIMPLIFIED_WRITE_AFIRST_SUPPORTED eq 1 |
2648 | mov eax,[format] |
2648 | mov eax,[format] |
2649 | and eax,PNG_FORMAT_FLAG_AFIRST |
2649 | and eax,PNG_FORMAT_FLAG_AFIRST |
2650 | jz .end13 ;if (..!=0) |
2650 | jz .end13 ;if (..!=0) |
2651 | cmp dword[colormap],0 |
2651 | cmp dword[colormap],0 |
2652 | jne @f |
2652 | jne @f |
2653 | mov eax,[format] |
2653 | mov eax,[format] |
2654 | and eax,PNG_FORMAT_FLAG_ALPHA |
2654 | and eax,PNG_FORMAT_FLAG_ALPHA |
2655 | jz @f ;if (..==0 && ..!=0) |
2655 | jz @f ;if (..==0 && ..!=0) |
2656 | stdcall png_set_swap_alpha, edi |
2656 | stdcall png_set_swap_alpha, edi |
2657 | @@: |
2657 | @@: |
2658 | and dword[format], not PNG_FORMAT_FLAG_AFIRST |
2658 | and dword[format], not PNG_FORMAT_FLAG_AFIRST |
2659 | .end13: |
2659 | .end13: |
2660 | end if |
2660 | end if |
2661 | 2661 | ||
2662 | ; If there are 16 or fewer color-map entries we wrote a lower bit depth |
2662 | ; If there are 16 or fewer color-map entries we wrote a lower bit depth |
2663 | ; above, but the application data is still byte packed. |
2663 | ; above, but the application data is still byte packed. |
2664 | 2664 | ||
2665 | cmp dword[colormap],0 |
2665 | cmp dword[colormap],0 |
2666 | je @f |
2666 | je @f |
2667 | cmp dword[ebx+png_image.colormap_entries],16 |
2667 | cmp dword[ebx+png_image.colormap_entries],16 |
2668 | jg @f ;if (..!=0 && ..<=16) |
2668 | jg @f ;if (..!=0 && ..<=16) |
2669 | stdcall png_set_packing, edi |
2669 | stdcall png_set_packing, edi |
2670 | @@: |
2670 | @@: |
2671 | 2671 | ||
2672 | ; That should have handled all (both) the transforms. |
2672 | ; That should have handled all (both) the transforms. |
2673 | mov eax,[format] |
2673 | mov eax,[format] |
2674 | and eax, not (PNG_FORMAT_FLAG_COLOR or PNG_FORMAT_FLAG_LINEAR or PNG_FORMAT_FLAG_ALPHA or PNG_FORMAT_FLAG_COLORMAP) |
2674 | and eax, not (PNG_FORMAT_FLAG_COLOR or PNG_FORMAT_FLAG_LINEAR or PNG_FORMAT_FLAG_ALPHA or PNG_FORMAT_FLAG_COLORMAP) |
2675 | jz @f ;if (..!=0) |
2675 | jz @f ;if (..!=0) |
2676 | png_error edi, 'png_write_image: unsupported transformation' |
2676 | png_error edi, 'png_write_image: unsupported transformation' |
2677 | @@: |
2677 | @@: |
2678 | 2678 | ||
2679 | push esi |
2679 | push esi |
2680 | ;ecx - row ;bytep |
2680 | ;ecx - row ;bytep |
2681 | ;esi - row_bytes |
2681 | ;esi - row_bytes |
2682 | mov ecx,[edx+png_image_write_control.buffer] |
2682 | mov ecx,[edx+png_image_write_control.buffer] |
2683 | mov esi,[edx+png_image_write_control.row_stride] |
2683 | mov esi,[edx+png_image_write_control.row_stride] |
2684 | 2684 | ||
2685 | cmp dword[linear],0 |
2685 | cmp dword[linear],0 |
2686 | je @f ;if (..!=0) |
2686 | je @f ;if (..!=0) |
2687 | shl esi,1 ;*= sizeof.uint_16 |
2687 | shl esi,1 ;*= sizeof.uint_16 |
2688 | @@: |
2688 | @@: |
2689 | cmp esi,0 |
2689 | cmp esi,0 |
2690 | jge @f ;if (..<0) |
2690 | jge @f ;if (..<0) |
2691 | mov eax,[ebx+png_image.height] |
2691 | mov eax,[ebx+png_image.height] |
2692 | dec eax |
2692 | dec eax |
2693 | imul eax,esi |
2693 | imul eax,esi |
2694 | sub ecx,eax |
2694 | sub ecx,eax |
2695 | @@: |
2695 | @@: |
2696 | mov [edx+png_image_write_control.first_row],ecx |
2696 | mov [edx+png_image_write_control.first_row],ecx |
2697 | mov [edx+png_image_write_control.row_bytes],esi |
2697 | mov [edx+png_image_write_control.row_bytes],esi |
2698 | pop esi |
2698 | pop esi |
2699 | 2699 | ||
2700 | ; Apply 'fast' options if the flag is set. |
2700 | ; Apply 'fast' options if the flag is set. |
2701 | mov eax,[ebx+png_image.flags] |
2701 | mov eax,[ebx+png_image.flags] |
2702 | and eax,PNG_IMAGE_FLAG_FAST |
2702 | and eax,PNG_IMAGE_FLAG_FAST |
2703 | jz @f ;if (..!=0) |
2703 | jz @f ;if (..!=0) |
2704 | stdcall png_set_filter, edi, PNG_FILTER_TYPE_BASE, PNG_NO_FILTERS |
2704 | stdcall png_set_filter, edi, PNG_FILTER_TYPE_BASE, PNG_NO_FILTERS |
2705 | ; NOTE: determined by experiment using pngstest, this reflects some |
2705 | ; NOTE: determined by experiment using pngstest, this reflects some |
2706 | ; balance between the time to write the image once and the time to read |
2706 | ; balance between the time to write the image once and the time to read |
2707 | ; it about 50 times. The speed-up in pngstest was about 10-20% of the |
2707 | ; it about 50 times. The speed-up in pngstest was about 10-20% of the |
2708 | ; total (user) time on a heavily loaded system. |
2708 | ; total (user) time on a heavily loaded system. |
2709 | 2709 | ||
2710 | if PNG_WRITE_CUSTOMIZE_COMPRESSION_SUPPORTED eq 1 |
2710 | if PNG_WRITE_CUSTOMIZE_COMPRESSION_SUPPORTED eq 1 |
2711 | stdcall png_set_compression_level, edi, 3 |
2711 | stdcall png_set_compression_level, edi, 3 |
2712 | end if |
2712 | end if |
2713 | @@: |
2713 | @@: |
2714 | 2714 | ||
2715 | ; Check for the cases that currently require a pre-transform on the row |
2715 | ; Check for the cases that currently require a pre-transform on the row |
2716 | ; before it is written. This only applies when the input is 16-bit and |
2716 | ; before it is written. This only applies when the input is 16-bit and |
2717 | ; either there is an alpha channel or it is converted to 8-bit. |
2717 | ; either there is an alpha channel or it is converted to 8-bit. |
2718 | 2718 | ||
2719 | cmp dword[linear],0 |
2719 | cmp dword[linear],0 |
2720 | je @f |
2720 | je @f |
2721 | cmp dword[alpha],0 |
2721 | cmp dword[alpha],0 |
2722 | je @f |
2722 | je @f |
2723 | jmp .end10 |
2723 | jmp .end10 |
2724 | @@: |
2724 | @@: |
2725 | cmp dword[colormap],0 |
2725 | cmp dword[colormap],0 |
2726 | jne .end9 |
2726 | jne .end9 |
2727 | cmp dword[edx+png_image_write_control.convert_to_8bit],0 |
2727 | cmp dword[edx+png_image_write_control.convert_to_8bit],0 |
2728 | je .end9 |
2728 | je .end9 |
2729 | .end10: ;if ((..!=0 && ..!=0 ) || (..==0 && ..!=0)) |
2729 | .end10: ;if ((..!=0 && ..!=0 ) || (..==0 && ..!=0)) |
2730 | stdcall png_get_rowbytes, edi, esi |
2730 | stdcall png_get_rowbytes, edi, esi |
2731 | stdcall png_malloc, edi, eax |
2731 | stdcall png_malloc, edi, eax |
2732 | mov ecx,eax ;ecx = row |
2732 | mov ecx,eax ;ecx = row |
2733 | 2733 | ||
2734 | mov [edx+png_image_write_control.local_row],ecx |
2734 | mov [edx+png_image_write_control.local_row],ecx |
2735 | cmp dword[write_16bit],0 |
2735 | cmp dword[write_16bit],0 |
2736 | je @f ;if (..!=0) |
2736 | je @f ;if (..!=0) |
2737 | stdcall png_safe_execute, ebx, png_write_image_16bit, edx |
2737 | stdcall png_safe_execute, ebx, png_write_image_16bit, edx |
2738 | jmp .end11 |
2738 | jmp .end11 |
2739 | @@: ;else |
2739 | @@: ;else |
2740 | stdcall png_safe_execute, ebx, png_write_image_8bit, edx |
2740 | stdcall png_safe_execute, ebx, png_write_image_8bit, edx |
2741 | .end11: |
2741 | .end11: |
2742 | mov dword[edx+png_image_write_control.local_row],0 |
2742 | mov dword[edx+png_image_write_control.local_row],0 |
2743 | 2743 | ||
2744 | stdcall png_free, edi, ecx |
2744 | stdcall png_free, edi, ecx |
2745 | 2745 | ||
2746 | ; Skip the 'write_end' on error: |
2746 | ; Skip the 'write_end' on error: |
2747 | cmp eax,0 |
2747 | cmp eax,0 |
2748 | je .end_f ;if (..==0) return 0 |
2748 | je .end_f ;if (..==0) return 0 |
2749 | jmp .end8 |
2749 | jmp .end8 |
2750 | 2750 | ||
2751 | ; Otherwise this is the case where the input is in a format currently |
2751 | ; Otherwise this is the case where the input is in a format currently |
2752 | ; supported by the rest of the libpng write code; call it directly. |
2752 | ; supported by the rest of the libpng write code; call it directly. |
2753 | 2753 | ||
2754 | .end9: ;else |
2754 | .end9: ;else |
2755 | if 1 ;;; IDAT compress all |
2755 | if 1 ;;; IDAT compress all |
2756 | mov ecx,[edx+png_image_write_control.row_bytes] |
2756 | mov ecx,[edx+png_image_write_control.row_bytes] |
2757 | inc ecx |
2757 | inc ecx |
2758 | imul ecx,[ebx+png_image.height] |
2758 | imul ecx,[ebx+png_image.height] |
2759 | cmp ecx,1 |
2759 | cmp ecx,1 |
2760 | jl .end8 |
2760 | jl .end8 |
2761 | stdcall create_compress_IDAT, edi, [edx+png_image_write_control.first_row], ecx, [ebx+png_image.width], [ebx+png_image.height] |
2761 | stdcall create_compress_IDAT, edi, [edx+png_image_write_control.first_row], ecx, [ebx+png_image.width], [ebx+png_image.height] |
2762 | else ;;; not work, IDAT compress by lines |
2762 | else ;;; not work, IDAT compress by lines |
2763 | mov ecx,[ebx+png_image.height] |
2763 | mov ecx,[ebx+png_image.height] |
2764 | cmp ecx,1 |
2764 | cmp ecx,1 |
2765 | jl .end8 |
2765 | jl .end8 |
2766 | mov eax,[edx+png_image_write_control.first_row] |
2766 | mov eax,[edx+png_image_write_control.first_row] |
2767 | mov ebx,[edx+png_image_write_control.row_bytes] |
2767 | mov ebx,[edx+png_image_write_control.row_bytes] |
2768 | @@: |
2768 | @@: |
2769 | stdcall png_write_row, edi, eax |
2769 | stdcall png_write_row, edi, eax |
2770 | add eax, ebx |
2770 | add eax, ebx |
2771 | loop @b |
2771 | loop @b |
2772 | end if |
2772 | end if |
2773 | .end8: |
2773 | .end8: |
2774 | 2774 | ||
2775 | stdcall png_write_end, edi, esi |
2775 | stdcall png_write_end, edi, esi |
2776 | xor eax,eax |
2776 | xor eax,eax |
2777 | inc eax |
2777 | inc eax |
2778 | .end_f: |
2778 | .end_f: |
2779 | ret |
2779 | ret |
2780 | endp |
2780 | endp |
2781 | 2781 | ||
2782 | align 16 |
2782 | align 16 |
2783 | proc create_compress_IDAT, png_ptr:dword, buf:dword, len:dword, width:dword, height:dword |
2783 | proc create_compress_IDAT, png_ptr:dword, buf:dword, len:dword, width:dword, height:dword |
2784 | locals |
2784 | locals |
2785 | m1 dd ? ;memory for compress IDAT |
2785 | m1 dd ? ;memory for compress IDAT |
2786 | buf_f dd ? ;memory for IDAT |
2786 | buf_f dd ? ;memory for IDAT |
2787 | mins dd ? ;minimum sum |
2787 | mins dd ? ;minimum sum |
2788 | endl |
2788 | endl |
2789 | pushad |
2789 | pushad |
2790 | mov edi,[png_ptr] |
2790 | mov edi,[png_ptr] |
2791 | png_debug 1, 'IDAT compress all' |
2791 | png_debug 1, 'IDAT compress all' |
2792 | 2792 | ||
2793 | ;create buffer with filters |
2793 | ;create buffer with filters |
2794 | stdcall png_zalloc, edi, 1, [len] |
2794 | stdcall png_zalloc, edi, 1, [len] |
2795 | cmp eax,0 |
2795 | cmp eax,0 |
2796 | je .end_f |
2796 | je .end_f |
2797 | mov [buf_f],eax |
2797 | mov [buf_f],eax |
2798 | 2798 | ||
2799 | mov eax,ZLIB_IO_MAX |
2799 | mov eax,ZLIB_IO_MAX |
2800 | cmp eax,[len] |
2800 | cmp eax,[len] |
2801 | jge @f |
2801 | jge @f |
2802 | mov eax,[len] |
2802 | mov eax,[len] |
2803 | @@: |
2803 | @@: |
2804 | stdcall png_zalloc, edi, 1, eax |
2804 | stdcall png_zalloc, edi, 1, eax |
2805 | cmp eax,0 |
2805 | cmp eax,0 |
2806 | je .end0 |
2806 | je .end0 |
2807 | mov [m1],eax |
2807 | mov [m1],eax |
2808 | 2808 | ||
2809 | ;init buffer with filters |
2809 | ;init buffer with filters |
2810 | mov ebx,[width] |
2810 | mov ebx,[width] |
2811 | mov edx,[height] |
2811 | mov edx,[height] |
2812 | mov edi,[buf_f] |
2812 | mov edi,[buf_f] |
2813 | mov esi,[buf] |
2813 | mov esi,[buf] |
2814 | .cycle0: |
2814 | .cycle0: |
2815 | cmp edx,1 |
2815 | cmp edx,1 |
2816 | jl .cycle0end |
2816 | jl .cycle0end |
2817 | mov ecx,ebx |
2817 | mov ecx,ebx |
2818 | xor al,al |
2818 | xor al,al |
2819 | stosb ;insert filter (0 - none) |
2819 | stosb ;insert filter (0 - none) |
2820 | align 4 |
2820 | align 4 |
2821 | .cycle1: |
2821 | .cycle1: |
2822 | lodsb ;1 |
2822 | lodsb ;1 |
2823 | inc edi ; |
2823 | inc edi ; |
2824 | movsb ;2 |
2824 | movsb ;2 |
2825 | stosb ;3 |
2825 | stosb ;3 |
2826 | lodsb ; |
2826 | lodsb ; |
2827 | mov [edi-3],al |
2827 | mov [edi-3],al |
2828 | loop .cycle1 |
2828 | loop .cycle1 |
2829 | dec edx |
2829 | dec edx |
2830 | jmp .cycle0 |
2830 | jmp .cycle0 |
2831 | .cycle0end: |
2831 | .cycle0end: |
2832 | 2832 | ||
2833 | ;make filters |
2833 | ;make filters |
2834 | mov edx,[height] |
2834 | mov edx,[height] |
2835 | mov esi,[width] |
2835 | mov esi,[width] |
2836 | imul esi,3 ;esi - rowbytes |
2836 | imul esi,3 ;esi - rowbytes |
2837 | 2837 | ||
2838 | inc esi |
2838 | inc esi |
2839 | mov edi,[png_ptr] |
2839 | mov edi,[png_ptr] |
2840 | cmp dword[edi+png_struct.try_row],0 |
2840 | cmp dword[edi+png_struct.try_row],0 |
2841 | jne @f ;if (..==0) |
2841 | jne @f ;if (..==0) |
2842 | stdcall png_malloc, edi, esi |
2842 | stdcall png_malloc, edi, esi |
2843 | mov [edi+png_struct.try_row],eax |
2843 | mov [edi+png_struct.try_row],eax |
2844 | @@: |
2844 | @@: |
2845 | cmp dword[edi+png_struct.tst_row],0 |
2845 | cmp dword[edi+png_struct.tst_row],0 |
2846 | jne @f ;if (..==0) |
2846 | jne @f ;if (..==0) |
2847 | stdcall png_malloc, edi, esi |
2847 | stdcall png_malloc, edi, esi |
2848 | mov [edi+png_struct.tst_row],eax |
2848 | mov [edi+png_struct.tst_row],eax |
2849 | @@: |
2849 | @@: |
2850 | dec esi |
2850 | dec esi |
2851 | 2851 | ||
2852 | mov edi,[buf_f] |
2852 | mov edi,[buf_f] |
2853 | add edi,[len] |
2853 | add edi,[len] |
2854 | .cycle3: |
2854 | .cycle3: |
2855 | dec edx |
2855 | dec edx |
2856 | cmp edx,1 |
2856 | cmp edx,1 |
2857 | jl .cycle3end |
2857 | jl .cycle3end |
2858 | sub edi,esi |
2858 | sub edi,esi |
2859 | dec edi ;move in perv row |
2859 | dec edi ;move in perv row |
2860 | 2860 | ||
2861 | ;init pointers for function png_setup_up_row |
2861 | ;init pointers for function png_setup_up_row |
2862 | mov ebx,[png_ptr] |
2862 | mov ebx,[png_ptr] |
2863 | mov [ebx+png_struct.row_buf],edi |
2863 | mov [ebx+png_struct.row_buf],edi |
2864 | mov [ebx+png_struct.prev_row],edi |
2864 | mov [ebx+png_struct.prev_row],edi |
2865 | sub [ebx+png_struct.prev_row],esi |
2865 | sub [ebx+png_struct.prev_row],esi |
2866 | dec dword[ebx+png_struct.prev_row] |
2866 | dec dword[ebx+png_struct.prev_row] |
2867 | 2867 | ||
2868 | ;calculate start minimum sum |
2868 | ;calculate start minimum sum |
2869 | push esi |
2869 | push esi |
2870 | xor eax,eax |
2870 | xor eax,eax |
2871 | xor ebx,ebx |
2871 | xor ebx,ebx |
2872 | mov ecx,esi |
2872 | mov ecx,esi |
2873 | mov esi,edi |
2873 | mov esi,edi |
2874 | inc esi |
2874 | inc esi |
2875 | .cycle2: |
2875 | .cycle2: |
2876 | lodsb |
2876 | lodsb |
2877 | png_setup_abs ebx |
2877 | png_setup_abs ebx |
2878 | loop .cycle2 |
2878 | loop .cycle2 |
2879 | pop esi |
2879 | pop esi |
2880 | mov [mins],ebx |
2880 | mov [mins],ebx |
2881 | 2881 | ||
2882 | push edx |
2882 | push edx |
2883 | mov edx,[png_ptr] |
2883 | mov edx,[png_ptr] |
2884 | mov eax,[edx+png_struct.tst_row] |
2884 | mov eax,[edx+png_struct.tst_row] |
2885 | mov byte[eax],0 ;not filter |
2885 | mov byte[eax],0 ;not filter |
2886 | 2886 | ||
2887 | ; Up filter |
2887 | ; Up filter |
2888 | stdcall png_setup_up_row, edx, esi, [mins] |
2888 | stdcall png_setup_up_row, edx, esi, [mins] |
2889 | cmp eax,[mins] |
2889 | cmp eax,[mins] |
2890 | jge @f ;if (..<..) |
2890 | jge @f ;if (..<..) |
2891 | mov [mins],eax |
2891 | mov [mins],eax |
2892 | stdcall copy_row_mins, [edx+png_struct.tst_row], [edx+png_struct.try_row] |
2892 | stdcall copy_row_mins, [edx+png_struct.tst_row], [edx+png_struct.try_row] |
2893 | @@: |
2893 | @@: |
2894 | 2894 | ||
2895 | ; Find out how many bytes offset each pixel is |
2895 | ; Find out how many bytes offset each pixel is |
2896 | movzx ebx,byte[edx+png_struct.pixel_depth] |
2896 | movzx ebx,byte[edx+png_struct.pixel_depth] |
2897 | add ebx,7 |
2897 | add ebx,7 |
2898 | shr ebx,3 |
2898 | shr ebx,3 |
2899 | 2899 | ||
2900 | ; Sub filter |
2900 | ; Sub filter |
2901 | stdcall png_setup_sub_row, edx, ebx, esi, [mins] |
2901 | stdcall png_setup_sub_row, edx, ebx, esi, [mins] |
2902 | cmp eax,[mins] |
2902 | cmp eax,[mins] |
2903 | jge @f ;if (..<..) |
2903 | jge @f ;if (..<..) |
2904 | mov [mins],eax |
2904 | mov [mins],eax |
2905 | stdcall copy_row_mins, [edx+png_struct.tst_row], [edx+png_struct.try_row] |
2905 | stdcall copy_row_mins, [edx+png_struct.tst_row], [edx+png_struct.try_row] |
2906 | @@: |
2906 | @@: |
2907 | 2907 | ||
2908 | ; Avg filter |
2908 | ; Avg filter |
2909 | stdcall png_setup_avg_row, edx, ebx, esi, [mins] |
2909 | stdcall png_setup_avg_row, edx, ebx, esi, [mins] |
2910 | cmp eax,[mins] |
2910 | cmp eax,[mins] |
2911 | jge @f ;if (..<..) |
2911 | jge @f ;if (..<..) |
2912 | mov [mins],eax |
2912 | mov [mins],eax |
2913 | stdcall copy_row_mins, [edx+png_struct.tst_row], [edx+png_struct.try_row] |
2913 | stdcall copy_row_mins, [edx+png_struct.tst_row], [edx+png_struct.try_row] |
2914 | @@: |
2914 | @@: |
2915 | 2915 | ||
2916 | ; Copy best row |
2916 | ; Copy best row |
2917 | mov eax,[edx+png_struct.tst_row] |
2917 | mov eax,[edx+png_struct.tst_row] |
2918 | cmp byte[eax],0 |
2918 | cmp byte[eax],0 |
2919 | je @f |
2919 | je @f |
2920 | stdcall copy_row_mins, edi, [edx+png_struct.tst_row] |
2920 | stdcall copy_row_mins, edi, [edx+png_struct.tst_row] |
2921 | @@: |
2921 | @@: |
2922 | pop edx |
2922 | pop edx |
2923 | jmp .cycle3 |
2923 | jmp .cycle3 |
2924 | .cycle3end: |
2924 | .cycle3end: |
2925 | 2925 | ||
2926 | mov edi,[png_ptr] |
2926 | mov edi,[png_ptr] |
2927 | mov esi,edi |
2927 | mov esi,edi |
2928 | add esi,png_struct.zstream |
2928 | add esi,png_struct.zstream |
2929 | stdcall [deflateInit2], esi,\ |
2929 | stdcall [deflateInit2], esi,\ |
2930 | -1, Z_DEFLATED, MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY |
2930 | -1, Z_DEFLATED, MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY |
2931 | 2931 | ||
2932 | mov eax,[buf_f] |
2932 | mov eax,[buf_f] |
2933 | mov [edi+png_struct.zstream.next_in],eax |
2933 | mov [edi+png_struct.zstream.next_in],eax |
2934 | mov eax,[len] |
2934 | mov eax,[len] |
2935 | mov [edi+png_struct.zstream.avail_in],eax |
2935 | mov [edi+png_struct.zstream.avail_in],eax |
2936 | mov eax,[m1] |
2936 | mov eax,[m1] |
2937 | mov [edi+png_struct.zstream.next_out],eax |
2937 | mov [edi+png_struct.zstream.next_out],eax |
2938 | xor ecx,ecx |
2938 | xor ecx,ecx |
2939 | align 4 |
2939 | align 4 |
2940 | .cycle4: |
2940 | .cycle4: |
2941 | mov dword[edi+png_struct.zstream.avail_out],16*1024 |
2941 | mov dword[edi+png_struct.zstream.avail_out],16*1024 |
2942 | 2942 | ||
2943 | stdcall [deflate], esi, Z_NO_FLUSH |
2943 | stdcall [deflate], esi, Z_FINISH ;Z_NO_FLUSH |
2944 | cmp eax,Z_STREAM_ERROR |
2944 | cmp eax,Z_STREAM_ERROR |
2945 | je .end1 |
2945 | je .end1 |
2946 | 2946 | ||
2947 | add ecx,16*1024 |
2947 | add ecx,16*1024 |
2948 | sub ecx,[edi+png_struct.zstream.avail_out] |
2948 | sub ecx,[edi+png_struct.zstream.avail_out] |
2949 | cmp dword[edi+png_struct.zstream.avail_out],0 |
2949 | cmp dword[edi+png_struct.zstream.avail_out],0 |
2950 | je .cycle4 ;while (strm.avail_out == 0) |
2950 | je .cycle4 ;while (strm.avail_out == 0) |
2951 | mov dword[edi+png_struct.zstream.avail_out],16*1024 |
2951 | if 0 |
- | 2952 | mov dword[edi+png_struct.zstream.avail_out],16*1024 |
|
2952 | stdcall [deflate], esi, Z_FINISH |
2953 | stdcall [deflate], esi, Z_FINISH |
2953 | add ecx,16*1024 |
2954 | add ecx,16*1024 |
2954 | sub ecx,[edi+png_struct.zstream.avail_out] |
2955 | sub ecx,[edi+png_struct.zstream.avail_out] |
2955 | cmp eax,Z_STREAM_ERROR |
2956 | cmp eax,Z_STREAM_ERROR |
2956 | je .end1 |
2957 | je .end1 |
2957 | 2958 | end if |
|
2958 | stdcall [deflateEnd], esi |
2959 | stdcall [deflateEnd], esi |
2959 | 2960 | ||
2960 | if PNG_WRITE_OPTIMIZE_CMF_SUPPORTED eq 1 |
2961 | if PNG_WRITE_OPTIMIZE_CMF_SUPPORTED eq 1 |
2961 | mov eax,[edi+png_struct.mode] |
2962 | mov eax,[edi+png_struct.mode] |
2962 | and eax,PNG_HAVE_IDAT |
2963 | and eax,PNG_HAVE_IDAT |
2963 | jnz @f |
2964 | jnz @f |
2964 | cmp byte[edi+png_struct.compression_type],PNG_COMPRESSION_TYPE_BASE |
2965 | cmp byte[edi+png_struct.compression_type],PNG_COMPRESSION_TYPE_BASE |
2965 | jne @f ;if (..==0 && ..==..) |
2966 | jne @f ;if (..==0 && ..==..) |
2966 | stdcall png_image_size, edi |
2967 | stdcall png_image_size, edi |
2967 | stdcall optimize_cmf, [m1], eax |
2968 | stdcall optimize_cmf, [m1], eax |
2968 | @@: |
2969 | @@: |
2969 | end if |
2970 | end if |
2970 | stdcall png_write_complete_chunk, edi, png_IDAT, [m1], ecx |
2971 | stdcall png_write_complete_chunk, edi, png_IDAT, [m1], ecx |
2971 | or dword[edi+png_struct.mode],PNG_HAVE_IDAT |
2972 | or dword[edi+png_struct.mode],PNG_HAVE_IDAT |
2972 | 2973 | ||
2973 | jmp @f |
2974 | jmp @f |
2974 | .end1: |
2975 | .end1: |
2975 | png_debug 1, 'Z_STREAM_ERROR' |
2976 | png_debug 1, 'Z_STREAM_ERROR' |
2976 | @@: |
2977 | @@: |
2977 | 2978 | ||
2978 | ;free memory |
2979 | ;free memory |
2979 | cmp dword[edi+png_struct.try_row],0 |
2980 | cmp dword[edi+png_struct.try_row],0 |
2980 | je @f ;if (..!=0) |
2981 | je @f ;if (..!=0) |
2981 | stdcall png_free, edi, [edi+png_struct.try_row] |
2982 | stdcall png_free, edi, [edi+png_struct.try_row] |
2982 | mov dword[edi+png_struct.try_row],0 |
2983 | mov dword[edi+png_struct.try_row],0 |
2983 | @@: |
2984 | @@: |
2984 | cmp dword[edi+png_struct.tst_row],0 |
2985 | cmp dword[edi+png_struct.tst_row],0 |
2985 | je @f ;if (..!=0) |
2986 | je @f ;if (..!=0) |
2986 | stdcall png_free, edi, [edi+png_struct.tst_row] |
2987 | stdcall png_free, edi, [edi+png_struct.tst_row] |
2987 | mov dword[edi+png_struct.tst_row],0 |
2988 | mov dword[edi+png_struct.tst_row],0 |
2988 | @@: |
2989 | @@: |
2989 | stdcall png_free, edi, [m1] |
2990 | stdcall png_free, edi, [m1] |
2990 | .end0: |
2991 | .end0: |
2991 | stdcall png_free, edi, [buf_f] |
2992 | stdcall png_free, edi, [buf_f] |
2992 | .end_f: |
2993 | .end_f: |
2993 | popad |
2994 | popad |
2994 | ret |
2995 | ret |
2995 | endp |
2996 | endp |
2996 | 2997 | ||
2997 | ;input: |
2998 | ;input: |
2998 | ; esi - rowbytes |
2999 | ; esi - rowbytes |
2999 | align 4 |
3000 | align 4 |
3000 | proc copy_row_mins uses edi esi, dest:dword, sour:dword |
3001 | proc copy_row_mins uses edi esi, dest:dword, sour:dword |
3001 | mov ecx,esi |
3002 | mov ecx,esi |
3002 | inc ecx |
3003 | inc ecx |
3003 | mov edi,[dest] |
3004 | mov edi,[dest] |
3004 | mov esi,[sour] |
3005 | mov esi,[sour] |
3005 | rep movsb |
3006 | rep movsb |
3006 | ret |
3007 | ret |
3007 | endp |
3008 | endp |
3008 | 3009 | ||
3009 | ;void (png_structp png_ptr, bytep/*const*/ data, png_size_t size) |
3010 | ;void (png_structp png_ptr, bytep/*const*/ data, png_size_t size) |
3010 | align 4 |
3011 | align 4 |
3011 | proc image_memory_write uses eax ebx ecx edi esi, png_ptr:dword, p2data:dword, size:dword |
3012 | proc image_memory_write uses eax ebx ecx edi esi, png_ptr:dword, p2data:dword, size:dword |
3012 | mov edi,[png_ptr] |
3013 | mov edi,[png_ptr] |
3013 | mov esi,[edi+png_struct.io_ptr] ;esi = png_image_write_control *display |
3014 | mov esi,[edi+png_struct.io_ptr] ;esi = png_image_write_control *display |
3014 | mov ebx,[esi+png_image_write_control.output_bytes] ;ebx = ob |
3015 | mov ebx,[esi+png_image_write_control.output_bytes] ;ebx = ob |
3015 | 3016 | ||
3016 | ; Check for overflow; this should never happen: |
3017 | ; Check for overflow; this should never happen: |
3017 | mov eax,PNG_SIZE_MAX |
3018 | mov eax,PNG_SIZE_MAX |
3018 | sub eax,ebx |
3019 | sub eax,ebx |
3019 | mov ecx,[size] |
3020 | mov ecx,[size] |
3020 | cmp ecx,eax |
3021 | cmp ecx,eax |
3021 | jg .end1 ;if (..<=..) |
3022 | jg .end1 ;if (..<=..) |
3022 | ; I don't think libpng ever does this, but just in case: |
3023 | ; I don't think libpng ever does this, but just in case: |
3023 | cmp ecx,0 |
3024 | cmp ecx,0 |
3024 | jle .end0 ;if (..>0) |
3025 | jle .end0 ;if (..>0) |
3025 | mov eax,ebx |
3026 | mov eax,ebx |
3026 | add eax,ecx |
3027 | add eax,ecx |
3027 | cmp [esi+png_image_write_control.memory_bytes],eax |
3028 | cmp [esi+png_image_write_control.memory_bytes],eax |
3028 | jl @f ;if (..>=..) ;writing |
3029 | jl @f ;if (..>=..) ;writing |
3029 | push esi |
3030 | push esi |
3030 | mov edi,[esi+png_image_write_control.memory] |
3031 | mov edi,[esi+png_image_write_control.memory] |
3031 | add edi,ebx |
3032 | add edi,ebx |
3032 | mov esi,[p2data] |
3033 | mov esi,[p2data] |
3033 | rep movsb ;memcpy(... |
3034 | rep movsb ;memcpy(... |
3034 | pop esi |
3035 | pop esi |
3035 | @@: |
3036 | @@: |
3036 | 3037 | ||
3037 | ; Always update the size: |
3038 | ; Always update the size: |
3038 | add ebx,[size] |
3039 | add ebx,[size] |
3039 | mov [esi+png_image_write_control.output_bytes],ebx |
3040 | mov [esi+png_image_write_control.output_bytes],ebx |
3040 | .end0: |
3041 | .end0: |
3041 | jmp .end2 |
3042 | jmp .end2 |
3042 | .end1: ;else |
3043 | .end1: ;else |
3043 | png_error edi, 'png_image_write_to_memory: PNG too big' |
3044 | png_error edi, 'png_image_write_to_memory: PNG too big' |
3044 | .end2: |
3045 | .end2: |
3045 | ret |
3046 | ret |
3046 | endp |
3047 | endp |
3047 | 3048 | ||
3048 | ;void (png_structp png_ptr) |
3049 | ;void (png_structp png_ptr) |
3049 | align 4 |
3050 | align 4 |
3050 | proc image_memory_flush, png_ptr:dword |
3051 | proc image_memory_flush, png_ptr:dword |
3051 | ret |
3052 | ret |
3052 | endp |
3053 | endp |
3053 | 3054 | ||
3054 | ;int (voidp argument) |
3055 | ;int (voidp argument) |
3055 | align 4 |
3056 | align 4 |
3056 | proc png_image_write_memory uses ebx, argument:dword |
3057 | proc png_image_write_memory uses ebx, argument:dword |
3057 | ; The rest of the memory-specific init and write_main in an error protected |
3058 | ; The rest of the memory-specific init and write_main in an error protected |
3058 | ; environment. This case needs to use callbacks for the write operations |
3059 | ; environment. This case needs to use callbacks for the write operations |
3059 | ; since libpng has no built in support for writing to memory. |
3060 | ; since libpng has no built in support for writing to memory. |
3060 | 3061 | ||
3061 | mov eax,[argument] |
3062 | mov eax,[argument] |
3062 | mov ebx,[eax+png_image_write_control.image] |
3063 | mov ebx,[eax+png_image_write_control.image] |
3063 | mov ebx,[ebx+png_image.opaque] |
3064 | mov ebx,[ebx+png_image.opaque] |
3064 | stdcall png_set_write_fn, [ebx+png_control.png_ptr], eax, image_memory_write, image_memory_flush |
3065 | stdcall png_set_write_fn, [ebx+png_control.png_ptr], eax, image_memory_write, image_memory_flush |
3065 | 3066 | ||
3066 | stdcall png_image_write_main, [argument] |
3067 | stdcall png_image_write_main, [argument] |
3067 | ret |
3068 | ret |
3068 | endp |
3069 | endp |
3069 | 3070 | ||
3070 | ;int (png_imagep image, void *memory, |
3071 | ;int (png_imagep image, void *memory, |
3071 | ; png_alloc_size_t * PNG_RESTRICT memory_bytes, int convert_to_8bit, |
3072 | ; png_alloc_size_t * PNG_RESTRICT memory_bytes, int convert_to_8bit, |
3072 | ; const void *buffer, int_32 row_stride, const void *colormap) |
3073 | ; const void *buffer, int_32 row_stride, const void *colormap) |
3073 | align 4 |
3074 | align 4 |
3074 | proc png_image_write_to_memory uses ebx ecx edx edi esi, image:dword, memory:dword,\ |
3075 | proc png_image_write_to_memory uses ebx ecx edx edi esi, image:dword, memory:dword,\ |
3075 | memory_bytes:dword, convert_to_8bit:dword, buffer:dword, row_stride:dword, colormap:dword |
3076 | memory_bytes:dword, convert_to_8bit:dword, buffer:dword, row_stride:dword, colormap:dword |
3076 | locals |
3077 | locals |
3077 | display png_image_write_control ;local struct |
3078 | display png_image_write_control ;local struct |
3078 | endl |
3079 | endl |
3079 | ;edi - display png_image_write_control |
3080 | ;edi - display png_image_write_control |
3080 | 3081 | ||
3081 | ; Write the image to the given buffer, or count the bytes if it is NULL |
3082 | ; Write the image to the given buffer, or count the bytes if it is NULL |
3082 | mov ebx,[image] |
3083 | mov ebx,[image] |
3083 | cmp ebx,0 |
3084 | cmp ebx,0 |
3084 | je .end0 |
3085 | je .end0 |
3085 | cmp dword[ebx+png_image.version],PNG_IMAGE_VERSION |
3086 | cmp dword[ebx+png_image.version],PNG_IMAGE_VERSION |
3086 | jne .end0 ;if (..!=0 && ..==..) |
3087 | jne .end0 ;if (..!=0 && ..==..) |
3087 | cmp dword[memory_bytes],0 |
3088 | cmp dword[memory_bytes],0 |
3088 | je .end2 |
3089 | je .end2 |
3089 | cmp dword[buffer],0 |
3090 | cmp dword[buffer],0 |
3090 | je .end2 ;if (..!=0 && ..!=0) |
3091 | je .end2 ;if (..!=0 && ..!=0) |
3091 | ; This is to give the caller an easier error detection in the NULL |
3092 | ; This is to give the caller an easier error detection in the NULL |
3092 | ; case and guard against uninitialized variable problems: |
3093 | ; case and guard against uninitialized variable problems: |
3093 | 3094 | ||
3094 | cmp dword[memory],0 |
3095 | cmp dword[memory],0 |
3095 | jne @f ;if(..==0) |
3096 | jne @f ;if(..==0) |
3096 | mov eax,[memory_bytes] |
3097 | mov eax,[memory_bytes] |
3097 | mov dword[eax],0 |
3098 | mov dword[eax],0 |
3098 | @@: |
3099 | @@: |
3099 | 3100 | ||
3100 | stdcall png_image_write_init, ebx |
3101 | stdcall png_image_write_init, ebx |
3101 | cmp eax,0 |
3102 | cmp eax,0 |
3102 | je .end3 ;if (..!=0) |
3103 | je .end3 ;if (..!=0) |
3103 | mov ecx,sizeof.png_image_write_control |
3104 | mov ecx,sizeof.png_image_write_control |
3104 | mov edi,ebp |
3105 | mov edi,ebp |
3105 | sub edi,ecx |
3106 | sub edi,ecx |
3106 | xor eax,eax |
3107 | xor eax,eax |
3107 | rep stosb ;memset(&display, 0, sizeof.display)) |
3108 | rep stosb ;memset(&display, 0, sizeof.display)) |
3108 | sub edi,sizeof.png_image_write_control |
3109 | sub edi,sizeof.png_image_write_control |
3109 | mov [edi+png_image_write_control.image],ebx |
3110 | mov [edi+png_image_write_control.image],ebx |
3110 | mov eax,[buffer] |
3111 | mov eax,[buffer] |
3111 | mov [edi+png_image_write_control.buffer],eax |
3112 | mov [edi+png_image_write_control.buffer],eax |
3112 | mov eax,[row_stride] |
3113 | mov eax,[row_stride] |
3113 | mov [edi+png_image_write_control.row_stride],eax |
3114 | mov [edi+png_image_write_control.row_stride],eax |
3114 | mov eax,[colormap] |
3115 | mov eax,[colormap] |
3115 | mov [edi+png_image_write_control.colormap],eax |
3116 | mov [edi+png_image_write_control.colormap],eax |
3116 | mov eax,[convert_to_8bit] |
3117 | mov eax,[convert_to_8bit] |
3117 | mov [edi+png_image_write_control.convert_to_8bit],eax |
3118 | mov [edi+png_image_write_control.convert_to_8bit],eax |
3118 | mov eax,[memory] |
3119 | mov eax,[memory] |
3119 | mov [edi+png_image_write_control.memory],eax |
3120 | mov [edi+png_image_write_control.memory],eax |
3120 | mov eax,[memory_bytes] |
3121 | mov eax,[memory_bytes] |
3121 | mov eax,[eax] |
3122 | mov eax,[eax] |
3122 | mov [edi+png_image_write_control.memory_bytes],eax |
3123 | mov [edi+png_image_write_control.memory_bytes],eax |
3123 | mov dword[edi+png_image_write_control.output_bytes], 0 |
3124 | mov dword[edi+png_image_write_control.output_bytes], 0 |
3124 | 3125 | ||
3125 | stdcall png_safe_execute, ebx, png_image_write_memory, edi |
3126 | stdcall png_safe_execute, ebx, png_image_write_memory, edi |
3126 | mov ecx,eax ;ecx = result |
3127 | mov ecx,eax ;ecx = result |
3127 | stdcall png_image_free, ebx |
3128 | stdcall png_image_free, ebx |
3128 | 3129 | ||
3129 | ; write_memory returns true even if we ran out of buffer. |
3130 | ; write_memory returns true even if we ran out of buffer. |
3130 | cmp ecx,0 ;if (..) |
3131 | cmp ecx,0 ;if (..) |
3131 | je .end4 |
3132 | je .end4 |
3132 | ; On out-of-buffer this function returns '0' but still updates |
3133 | ; On out-of-buffer this function returns '0' but still updates |
3133 | ; memory_bytes: |
3134 | ; memory_bytes: |
3134 | 3135 | ||
3135 | mov edx,[edi+png_image_write_control.output_bytes] |
3136 | mov edx,[edi+png_image_write_control.output_bytes] |
3136 | mov eax,[memory_bytes] |
3137 | mov eax,[memory_bytes] |
3137 | cmp dword[memory],0 |
3138 | cmp dword[memory],0 |
3138 | je @f ;if (..!=0 && ..>..) |
3139 | je @f ;if (..!=0 && ..>..) |
3139 | cmp edx,[eax] |
3140 | cmp edx,[eax] |
3140 | jle @f |
3141 | jle @f |
3141 | xor ecx,ecx |
3142 | xor ecx,ecx |
3142 | @@: |
3143 | @@: |
3143 | mov [eax],edx |
3144 | mov [eax],edx |
3144 | .end4: |
3145 | .end4: |
3145 | 3146 | ||
3146 | mov eax,ecx |
3147 | mov eax,ecx |
3147 | jmp .end_f |
3148 | jmp .end_f |
3148 | .end3: ;else |
3149 | .end3: ;else |
3149 | xor eax,eax |
3150 | xor eax,eax |
3150 | jmp .end_f |
3151 | jmp .end_f |
3151 | .end2: ;else |
3152 | .end2: ;else |
3152 | std_png_image_error ebx, 'png_image_write_to_memory: invalid argument' |
3153 | std_png_image_error ebx, 'png_image_write_to_memory: invalid argument' |
3153 | jmp .end_f |
3154 | jmp .end_f |
3154 | .end0: |
3155 | .end0: |
3155 | cmp ebx,0 |
3156 | cmp ebx,0 |
3156 | je .end1 ;else if (..!=0) |
3157 | je .end1 ;else if (..!=0) |
3157 | std_png_image_error ebx, 'png_image_write_to_memory: incorrect PNG_IMAGE_VERSION' |
3158 | std_png_image_error ebx, 'png_image_write_to_memory: incorrect PNG_IMAGE_VERSION' |
3158 | jmp .end_f |
3159 | jmp .end_f |
3159 | .end1: ;else |
3160 | .end1: ;else |
3160 | xor eax,eax |
3161 | xor eax,eax |
3161 | .end_f: |
3162 | .end_f: |
3162 | ret |
3163 | ret |
3163 | endp |
3164 | endp |
3164 | 3165 | ||
3165 | ;int (png_imagep image, FILE *file, int convert_to_8bit, |
3166 | ;int (png_imagep image, FILE *file, int convert_to_8bit, |
3166 | ; const void *buffer, int_32 row_stride, const void *colormap) |
3167 | ; const void *buffer, int_32 row_stride, const void *colormap) |
3167 | align 4 |
3168 | align 4 |
3168 | proc png_image_write_to_stdio, image:dword, file:dword, convert_to_8bit:dword, buffer:dword, row_stride:dword, colormap:dword |
3169 | proc png_image_write_to_stdio, image:dword, file:dword, convert_to_8bit:dword, buffer:dword, row_stride:dword, colormap:dword |
3169 | ; Write the image to the given (FILE*). |
3170 | ; Write the image to the given (FILE*). |
3170 | ; if (image != NULL && image->version == PNG_IMAGE_VERSION) |
3171 | ; if (image != NULL && image->version == PNG_IMAGE_VERSION) |
3171 | ; { |
3172 | ; { |
3172 | ; if (file != NULL && buffer != NULL) |
3173 | ; if (file != NULL && buffer != NULL) |
3173 | ; { |
3174 | ; { |
3174 | ; if (png_image_write_init(image) != 0) |
3175 | ; if (png_image_write_init(image) != 0) |
3175 | ; { |
3176 | ; { |
3176 | ; png_image_write_control display; |
3177 | ; png_image_write_control display; |
3177 | ; int result; |
3178 | ; int result; |
3178 | 3179 | ||
3179 | ; This is slightly evil, but png_init_io doesn't do anything other |
3180 | ; This is slightly evil, but png_init_io doesn't do anything other |
3180 | ; than this and we haven't changed the standard IO functions so |
3181 | ; than this and we haven't changed the standard IO functions so |
3181 | ; this saves a 'safe' function. |
3182 | ; this saves a 'safe' function. |
3182 | 3183 | ||
3183 | ; image->opaque->png_ptr->io_ptr = file; |
3184 | ; image->opaque->png_ptr->io_ptr = file; |
3184 | 3185 | ||
3185 | ; memset(&display, 0, (sizeof display)); |
3186 | ; memset(&display, 0, (sizeof display)); |
3186 | ; display.image = image; |
3187 | ; display.image = image; |
3187 | ; display.buffer = buffer; |
3188 | ; display.buffer = buffer; |
3188 | ; display.row_stride = row_stride; |
3189 | ; display.row_stride = row_stride; |
3189 | ; display.colormap = colormap; |
3190 | ; display.colormap = colormap; |
3190 | ; display.convert_to_8bit = convert_to_8bit; |
3191 | ; display.convert_to_8bit = convert_to_8bit; |
3191 | 3192 | ||
3192 | ; result = png_safe_execute(image, png_image_write_main, &display); |
3193 | ; result = png_safe_execute(image, png_image_write_main, &display); |
3193 | ; png_image_free(image); |
3194 | ; png_image_free(image); |
3194 | ; return result; |
3195 | ; return result; |
3195 | ; } |
3196 | ; } |
3196 | 3197 | ||
3197 | ; else |
3198 | ; else |
3198 | ; return 0; |
3199 | ; return 0; |
3199 | ; } |
3200 | ; } |
3200 | 3201 | ||
3201 | ; else |
3202 | ; else |
3202 | ; return png_image_error(image, |
3203 | ; return png_image_error(image, |
3203 | ; "png_image_write_to_stdio: invalid argument"); |
3204 | ; "png_image_write_to_stdio: invalid argument"); |
3204 | ; } |
3205 | ; } |
3205 | 3206 | ||
3206 | ; else if (image != NULL) |
3207 | ; else if (image != NULL) |
3207 | ; return png_image_error(image, |
3208 | ; return png_image_error(image, |
3208 | ; "png_image_write_to_stdio: incorrect PNG_IMAGE_VERSION"); |
3209 | ; "png_image_write_to_stdio: incorrect PNG_IMAGE_VERSION"); |
3209 | 3210 | ||
3210 | ; else |
3211 | ; else |
3211 | ; return 0; |
3212 | ; return 0; |
3212 | ret |
3213 | ret |
3213 | endp |
3214 | endp |
3214 | 3215 | ||
3215 | ;int (png_imagep image, const char *file_name, |
3216 | ;int (png_imagep image, const char *file_name, |
3216 | ; int convert_to_8bit, const void *buffer, int_32 row_stride, |
3217 | ; int convert_to_8bit, const void *buffer, int_32 row_stride, |
3217 | ; const void *colormap) |
3218 | ; const void *colormap) |
3218 | align 4 |
3219 | align 4 |
3219 | proc png_image_write_to_file, image:dword, file_name:dword, convert_to_8bit:dword, buffer:dword, row_stride:dword, colormap:dword |
3220 | proc png_image_write_to_file, image:dword, file_name:dword, convert_to_8bit:dword, buffer:dword, row_stride:dword, colormap:dword |
3220 | ; Write the image to the named file. |
3221 | ; Write the image to the named file. |
3221 | ; if (image != NULL && image->version == PNG_IMAGE_VERSION) |
3222 | ; if (image != NULL && image->version == PNG_IMAGE_VERSION) |
3222 | ; { |
3223 | ; { |
3223 | ; if (file_name != NULL && buffer != NULL) |
3224 | ; if (file_name != NULL && buffer != NULL) |
3224 | ; { |
3225 | ; { |
3225 | ; FILE *fp = fopen(file_name, "wb"); |
3226 | ; FILE *fp = fopen(file_name, "wb"); |
3226 | 3227 | ||
3227 | ; if (fp != NULL) |
3228 | ; if (fp != NULL) |
3228 | ; { |
3229 | ; { |
3229 | ; if (png_image_write_to_stdio(image, fp, convert_to_8bit, buffer, |
3230 | ; if (png_image_write_to_stdio(image, fp, convert_to_8bit, buffer, |
3230 | ; row_stride, colormap) != 0) |
3231 | ; row_stride, colormap) != 0) |
3231 | ; { |
3232 | ; { |
3232 | ; int error; /* from fflush/fclose */ |
3233 | ; int error; /* from fflush/fclose */ |
3233 | 3234 | ||
3234 | ; Make sure the file is flushed correctly. |
3235 | ; Make sure the file is flushed correctly. |
3235 | ; if (fflush(fp) == 0 && ferror(fp) == 0) |
3236 | ; if (fflush(fp) == 0 && ferror(fp) == 0) |
3236 | ; { |
3237 | ; { |
3237 | ; if (fclose(fp) == 0) |
3238 | ; if (fclose(fp) == 0) |
3238 | ; return 1; |
3239 | ; return 1; |
3239 | 3240 | ||
3240 | ; error = errno; /* from fclose */ |
3241 | ; error = errno; /* from fclose */ |
3241 | ; } |
3242 | ; } |
3242 | 3243 | ||
3243 | ; else |
3244 | ; else |
3244 | ; { |
3245 | ; { |
3245 | ; error = errno; /* from fflush or ferror */ |
3246 | ; error = errno; /* from fflush or ferror */ |
3246 | ; (void)fclose(fp); |
3247 | ; (void)fclose(fp); |
3247 | ; } |
3248 | ; } |
3248 | 3249 | ||
3249 | ; (void)remove(file_name); |
3250 | ; (void)remove(file_name); |
3250 | ; The image has already been cleaned up; this is just used to |
3251 | ; The image has already been cleaned up; this is just used to |
3251 | ; set the error (because the original write succeeded). |
3252 | ; set the error (because the original write succeeded). |
3252 | 3253 | ||
3253 | ; return png_image_error(image, strerror(error)); |
3254 | ; return png_image_error(image, strerror(error)); |
3254 | ; } |
3255 | ; } |
3255 | 3256 | ||
3256 | ; else |
3257 | ; else |
3257 | ; { |
3258 | ; { |
3258 | ; Clean up: just the opened file. |
3259 | ; Clean up: just the opened file. |
3259 | ; (void)fclose(fp); |
3260 | ; (void)fclose(fp); |
3260 | ; (void)remove(file_name); |
3261 | ; (void)remove(file_name); |
3261 | ; return 0; |
3262 | ; return 0; |
3262 | ; } |
3263 | ; } |
3263 | ; } |
3264 | ; } |
3264 | 3265 | ||
3265 | ; else |
3266 | ; else |
3266 | ; return png_image_error(image, strerror(errno)); |
3267 | ; return png_image_error(image, strerror(errno)); |
3267 | ; } |
3268 | ; } |
3268 | 3269 | ||
3269 | ; else |
3270 | ; else |
3270 | ; return png_image_error(image, |
3271 | ; return png_image_error(image, |
3271 | ; "png_image_write_to_file: invalid argument"); |
3272 | ; "png_image_write_to_file: invalid argument"); |
3272 | ; } |
3273 | ; } |
3273 | 3274 | ||
3274 | ; else if (image != NULL) |
3275 | ; else if (image != NULL) |
3275 | ; return png_image_error(image, |
3276 | ; return png_image_error(image, |
3276 | ; "png_image_write_to_file: incorrect PNG_IMAGE_VERSION"); |
3277 | ; "png_image_write_to_file: incorrect PNG_IMAGE_VERSION"); |
3277 | 3278 | ||
3278 | ; else |
3279 | ; else |
3279 | ; return 0; |
3280 | ; return 0; |
3280 | ret |
3281 | ret |
3281 | endp |
3282 | endp |
3282 | end if ;SIMPLIFIED_WRITE=..) |
3283 | end if ;SIMPLIFIED_WRITE=..) |
3283 | > |
3284 | > |
3284 | > |
3285 | > |
3285 | > |
3286 | > |
3286 | >0) |
3287 | >0) |
3287 | >=16) |
3288 | >=16) |
3288 | >0) |
3289 | >0) |
3289 | >=..)>>>>7)+(alpha><7)+(alpha>> |
3290 | >=..)>>>>7)+(alpha><7)+(alpha>> |
3290 | >>>>> |
3291 | >>>>> |
3291 | >7)+(alpha><7)+(alpha>>15)+(alpha><15)+(alpha>>><>> |
3292 | >7)+(alpha><7)+(alpha>>15)+(alpha><15)+(alpha>>><>> |
3292 | >=> |
3293 | >=> |
3293 | >=>> |
3294 | >=>> |
3294 | > |
3295 | > |
3295 | > |
3296 | > |
3296 | >><>><>><>>>>>>>> |
3297 | >><>><>><>>>>>>>> |
3297 | > |
3298 | > |