shailesh / pyglet

Automatically exported from code.google.com/p/pyglet
BSD 3-Clause "New" or "Revised" License
0 stars 0 forks source link

image.save('file.png') doesn't save modified img-data #708

Open GoogleCodeExporter opened 9 years ago

GoogleCodeExporter commented 9 years ago
Using pyglet-hg 1.2alpha1.2774.f8da1dcafc85-1

What steps will reproduce the problem?
1. Running this code: 
http://stackoverflow.com/questions/22017516/pyglets-image-savefile-png-doesnt-sa
ve-modifications-to-img-data

or

1. x = pyglet.image.SolidColorImagePattern(c).create_image(width, height)
2. modify data recieved from x.get_data(...)
3. modify texture by issuing x.set_data(modified_data) adding a green line
4. x.save('kitten.png')

There's no traceback or error message.. But after issuing .save() i still 
expect to be able to render x via x.draw(), but instead if shows up as a 100% 
transparent or just a blank object.. You can't see it.
Also the .save() will save a completely transparent image without the modified 
data.

Paste in the output of `python -m pyglet.info`:
Python
------------------------------------------------------------------------------
sys.version: 3.3.4 (default, Feb 11 2014, 15:56:08) 
[GCC 4.8.2 20140206 (prerelease)]
sys.platform: linux
sys.maxint: 9223372036854775807
os.getcwd(): /home/torxed

pyglet
------------------------------------------------------------------------------
pyglet.version: 1.2alpha1
pyglet.__file__: /usr/lib/python3.3/site-packages/pyglet/__init__.py
pyglet.options['xsync'] = True
pyglet.options['xlib_fullscreen_override_redirect'] = False
pyglet.options['shadow_window'] = True
pyglet.options['debug_x11'] = False
pyglet.options['debug_trace_depth'] = 1
pyglet.options['graphics_vbo'] = True
pyglet.options['debug_lib'] = False
pyglet.options['audio'] = ('directsound', 'pulse', 'openal', 'silent')
pyglet.options['darwin_cocoa'] = False
pyglet.options['debug_font'] = False
pyglet.options['debug_graphics_batch'] = False
pyglet.options['font'] = ('gdiplus', 'win32')
pyglet.options['debug_gl_trace_args'] = False
pyglet.options['debug_media'] = False
pyglet.options['debug_trace'] = False
pyglet.options['debug_trace_args'] = False
pyglet.options['debug_gl_trace'] = False
pyglet.options['vsync'] = None
pyglet.options['debug_win32'] = False
pyglet.options['debug_trace_flush'] = True
pyglet.options['debug_texture'] = False
pyglet.options['debug_gl'] = True

pyglet.window
------------------------------------------------------------------------------
platform: <pyglet.window.Platform object at 0x7f8ccaf96650>
display: <pyglet.canvas.xlib.XlibDisplay object at 0x7f8cc4ab51d0>
screens[0]: XlibScreen(display=<pyglet.canvas.xlib.XlibDisplay object at 
0x7f8cc4ab51d0>, x=0, y=0, width=1920, height=1080, xinerama=0)
config['double_buffer'] = 1
config['stereo'] = 0
config['buffer_size'] = 32
config['aux_buffers'] = 4
config['sample_buffers'] = 0
config['samples'] = 0
config['red_size'] = 8
config['green_size'] = 8
config['blue_size'] = 8
config['alpha_size'] = 0
config['depth_size'] = 24
config['stencil_size'] = 0
config['accum_red_size'] = 16
config['accum_green_size'] = 16
config['accum_blue_size'] = 16
config['accum_alpha_size'] = 16
config['major_version'] = None
config['minor_version'] = None
config['forward_compatible'] = None
config['debug'] = None
context: XlibContextARB()

window.context._info
------------------------------------------------------------------------------
gl_info.get_version(): 4.4.0 NVIDIA 331.38
gl_info.get_vendor(): NVIDIA Corporation
gl_info.get_renderer(): Quadro 3000M/PCIe/SSE2
gl_info.get_extensions():
   GL_AMD_multi_draw_indirect
   GL_ARB_ES2_compatibility
   GL_ARB_ES3_compatibility
   GL_ARB_arrays_of_arrays
   GL_ARB_base_instance
   GL_ARB_blend_func_extended
   GL_ARB_buffer_storage
   GL_ARB_clear_buffer_object
   GL_ARB_clear_texture
   GL_ARB_color_buffer_float
   GL_ARB_compatibility
   GL_ARB_compressed_texture_pixel_storage
   GL_ARB_compute_shader
   GL_ARB_compute_variable_group_size
   GL_ARB_conservative_depth
   GL_ARB_copy_buffer
   GL_ARB_copy_image
   GL_ARB_debug_output
   GL_ARB_depth_buffer_float
   GL_ARB_depth_clamp
   GL_ARB_depth_texture
   GL_ARB_draw_buffers
   GL_ARB_draw_buffers_blend
   GL_ARB_draw_elements_base_vertex
   GL_ARB_draw_indirect
   GL_ARB_draw_instanced
   GL_ARB_enhanced_layouts
   GL_ARB_explicit_attrib_location
   GL_ARB_explicit_uniform_location
   GL_ARB_fragment_coord_conventions
   GL_ARB_fragment_layer_viewport
   GL_ARB_fragment_program
   GL_ARB_fragment_program_shadow
   GL_ARB_fragment_shader
   GL_ARB_framebuffer_no_attachments
   GL_ARB_framebuffer_object
   GL_ARB_framebuffer_sRGB
   GL_ARB_geometry_shader4
   GL_ARB_get_program_binary
   GL_ARB_gpu_shader5
   GL_ARB_gpu_shader_fp64
   GL_ARB_half_float_pixel
   GL_ARB_half_float_vertex
   GL_ARB_imaging
   GL_ARB_indirect_parameters
   GL_ARB_instanced_arrays
   GL_ARB_internalformat_query
   GL_ARB_internalformat_query2
   GL_ARB_invalidate_subdata
   GL_ARB_map_buffer_alignment
   GL_ARB_map_buffer_range
   GL_ARB_multi_bind
   GL_ARB_multi_draw_indirect
   GL_ARB_multisample
   GL_ARB_multitexture
   GL_ARB_occlusion_query
   GL_ARB_occlusion_query2
   GL_ARB_pixel_buffer_object
   GL_ARB_point_parameters
   GL_ARB_point_sprite
   GL_ARB_program_interface_query
   GL_ARB_provoking_vertex
   GL_ARB_query_buffer_object
   GL_ARB_robust_buffer_access_behavior
   GL_ARB_robustness
   GL_ARB_sample_shading
   GL_ARB_sampler_objects
   GL_ARB_seamless_cube_map
   GL_ARB_separate_shader_objects
   GL_ARB_shader_atomic_counters
   GL_ARB_shader_bit_encoding
   GL_ARB_shader_draw_parameters
   GL_ARB_shader_group_vote
   GL_ARB_shader_image_load_store
   GL_ARB_shader_image_size
   GL_ARB_shader_objects
   GL_ARB_shader_precision
   GL_ARB_shader_storage_buffer_object
   GL_ARB_shader_subroutine
   GL_ARB_shader_texture_lod
   GL_ARB_shading_language_100
   GL_ARB_shading_language_420pack
   GL_ARB_shading_language_include
   GL_ARB_shading_language_packing
   GL_ARB_shadow
   GL_ARB_sparse_texture
   GL_ARB_stencil_texturing
   GL_ARB_sync
   GL_ARB_tessellation_shader
   GL_ARB_texture_border_clamp
   GL_ARB_texture_buffer_object
   GL_ARB_texture_buffer_object_rgb32
   GL_ARB_texture_buffer_range
   GL_ARB_texture_compression
   GL_ARB_texture_compression_bptc
   GL_ARB_texture_compression_rgtc
   GL_ARB_texture_cube_map
   GL_ARB_texture_cube_map_array
   GL_ARB_texture_env_add
   GL_ARB_texture_env_combine
   GL_ARB_texture_env_crossbar
   GL_ARB_texture_env_dot3
   GL_ARB_texture_float
   GL_ARB_texture_gather
   GL_ARB_texture_mirror_clamp_to_edge
   GL_ARB_texture_mirrored_repeat
   GL_ARB_texture_multisample
   GL_ARB_texture_non_power_of_two
   GL_ARB_texture_query_levels
   GL_ARB_texture_query_lod
   GL_ARB_texture_rectangle
   GL_ARB_texture_rg
   GL_ARB_texture_rgb10_a2ui
   GL_ARB_texture_stencil8
   GL_ARB_texture_storage
   GL_ARB_texture_storage_multisample
   GL_ARB_texture_swizzle
   GL_ARB_texture_view
   GL_ARB_timer_query
   GL_ARB_transform_feedback2
   GL_ARB_transform_feedback3
   GL_ARB_transform_feedback_instanced
   GL_ARB_transpose_matrix
   GL_ARB_uniform_buffer_object
   GL_ARB_vertex_array_bgra
   GL_ARB_vertex_array_object
   GL_ARB_vertex_attrib_64bit
   GL_ARB_vertex_attrib_binding
   GL_ARB_vertex_buffer_object
   GL_ARB_vertex_program
   GL_ARB_vertex_shader
   GL_ARB_vertex_type_10f_11f_11f_rev
   GL_ARB_vertex_type_2_10_10_10_rev
   GL_ARB_viewport_array
   GL_ARB_window_pos
   GL_ATI_draw_buffers
   GL_ATI_texture_float
   GL_ATI_texture_mirror_once
   GL_EXTX_framebuffer_mixed_formats
   GL_EXT_Cg_shader
   GL_EXT_abgr
   GL_EXT_bgra
   GL_EXT_bindable_uniform
   GL_EXT_blend_color
   GL_EXT_blend_equation_separate
   GL_EXT_blend_func_separate
   GL_EXT_blend_minmax
   GL_EXT_blend_subtract
   GL_EXT_compiled_vertex_array
   GL_EXT_depth_bounds_test
   GL_EXT_direct_state_access
   GL_EXT_draw_buffers2
   GL_EXT_draw_instanced
   GL_EXT_draw_range_elements
   GL_EXT_fog_coord
   GL_EXT_framebuffer_blit
   GL_EXT_framebuffer_multisample
   GL_EXT_framebuffer_multisample_blit_scaled
   GL_EXT_framebuffer_object
   GL_EXT_framebuffer_sRGB
   GL_EXT_geometry_shader4
   GL_EXT_gpu_program_parameters
   GL_EXT_gpu_shader4
   GL_EXT_import_sync_object
   GL_EXT_multi_draw_arrays
   GL_EXT_packed_depth_stencil
   GL_EXT_packed_float
   GL_EXT_packed_pixels
   GL_EXT_pixel_buffer_object
   GL_EXT_point_parameters
   GL_EXT_provoking_vertex
   GL_EXT_rescale_normal
   GL_EXT_secondary_color
   GL_EXT_separate_shader_objects
   GL_EXT_separate_specular_color
   GL_EXT_shader_image_load_store
   GL_EXT_shadow_funcs
   GL_EXT_stencil_two_side
   GL_EXT_stencil_wrap
   GL_EXT_texture3D
   GL_EXT_texture_array
   GL_EXT_texture_buffer_object
   GL_EXT_texture_compression_dxt1
   GL_EXT_texture_compression_latc
   GL_EXT_texture_compression_rgtc
   GL_EXT_texture_compression_s3tc
   GL_EXT_texture_cube_map
   GL_EXT_texture_edge_clamp
   GL_EXT_texture_env_add
   GL_EXT_texture_env_combine
   GL_EXT_texture_env_dot3
   GL_EXT_texture_filter_anisotropic
   GL_EXT_texture_integer
   GL_EXT_texture_lod
   GL_EXT_texture_lod_bias
   GL_EXT_texture_mirror_clamp
   GL_EXT_texture_object
   GL_EXT_texture_sRGB
   GL_EXT_texture_sRGB_decode
   GL_EXT_texture_shared_exponent
   GL_EXT_texture_storage
   GL_EXT_texture_swizzle
   GL_EXT_timer_query
   GL_EXT_transform_feedback2
   GL_EXT_vertex_array
   GL_EXT_vertex_array_bgra
   GL_EXT_vertex_attrib_64bit
   GL_EXT_x11_sync_object
   GL_IBM_rasterpos_clip
   GL_IBM_texture_mirrored_repeat
   GL_KHR_debug
   GL_KTX_buffer_region
   GL_NVX_conditional_render
   GL_NVX_gpu_memory_info
   GL_NV_ES1_1_compatibility
   GL_NV_bindless_multi_draw_indirect
   GL_NV_blend_equation_advanced
   GL_NV_blend_square
   GL_NV_compute_program5
   GL_NV_conditional_render
   GL_NV_copy_depth_to_color
   GL_NV_copy_image
   GL_NV_depth_buffer_float
   GL_NV_depth_clamp
   GL_NV_draw_texture
   GL_NV_explicit_multisample
   GL_NV_fence
   GL_NV_float_buffer
   GL_NV_fog_distance
   GL_NV_fragment_program
   GL_NV_fragment_program2
   GL_NV_fragment_program_option
   GL_NV_framebuffer_multisample_coverage
   GL_NV_geometry_shader4
   GL_NV_gpu_program4
   GL_NV_gpu_program4_1
   GL_NV_gpu_program5
   GL_NV_gpu_program5_mem_extended
   GL_NV_gpu_program_fp64
   GL_NV_gpu_shader5
   GL_NV_half_float
   GL_NV_light_max_exponent
   GL_NV_multisample_coverage
   GL_NV_multisample_filter_hint
   GL_NV_occlusion_query
   GL_NV_packed_depth_stencil
   GL_NV_parameter_buffer_object
   GL_NV_parameter_buffer_object2
   GL_NV_path_rendering
   GL_NV_pixel_data_range
   GL_NV_point_sprite
   GL_NV_primitive_restart
   GL_NV_register_combiners
   GL_NV_register_combiners2
   GL_NV_shader_atomic_counters
   GL_NV_shader_atomic_float
   GL_NV_shader_buffer_load
   GL_NV_shader_storage_buffer_object
   GL_NV_texgen_reflection
   GL_NV_texture_barrier
   GL_NV_texture_compression_vtc
   GL_NV_texture_env_combine4
   GL_NV_texture_expand_normal
   GL_NV_texture_multisample
   GL_NV_texture_rectangle
   GL_NV_texture_shader
   GL_NV_texture_shader2
   GL_NV_texture_shader3
   GL_NV_transform_feedback
   GL_NV_transform_feedback2
   GL_NV_vdpau_interop
   GL_NV_vertex_array_range
   GL_NV_vertex_array_range2
   GL_NV_vertex_attrib_integer_64bit
   GL_NV_vertex_buffer_unified_memory
   GL_NV_vertex_program
   GL_NV_vertex_program1_1
   GL_NV_vertex_program2
   GL_NV_vertex_program2_option
   GL_NV_vertex_program3
   GL_NV_video_capture
   GL_S3_s3tc
   GL_SGIS_generate_mipmap
   GL_SGIS_texture_lod
   GL_SGIX_depth_texture
   GL_SGIX_shadow
   GL_SUN_slice_accum

pyglet.gl.glu_info
------------------------------------------------------------------------------
glu_info.get_version(): 1.3
glu_info.get_extensions():
   GLU_EXT_nurbs_tessellator
   GLU_EXT_object_space_tess

pyglet.gl.glx_info
------------------------------------------------------------------------------
context.is_direct(): 1
glx_info.get_server_vendor(): NVIDIA Corporation
glx_info.get_server_version(): 1.4
glx_info.get_server_extensions():
   GLX_EXT_visual_info
   GLX_EXT_visual_rating
   GLX_SGIX_fbconfig
   GLX_SGIX_pbuffer
   GLX_SGI_video_sync
   GLX_SGI_swap_control
   GLX_EXT_swap_control
   GLX_EXT_swap_control_tear
   GLX_EXT_texture_from_pixmap
   GLX_EXT_buffer_age
   GLX_ARB_create_context
   GLX_ARB_create_context_profile
   GLX_EXT_create_context_es_profile
   GLX_EXT_create_context_es2_profile
   GLX_ARB_create_context_robustness
   GLX_ARB_multisample
   GLX_NV_float_buffer
   GLX_ARB_fbconfig_float
   GLX_NV_swap_group
   GLX_EXT_framebuffer_sRGB
   GLX_NV_multisample_coverage
   GLX_NV_copy_image
   GLX_NV_video_capture
glx_info.get_client_vendor(): NVIDIA Corporation
glx_info.get_client_version(): 1.4
glx_info.get_client_extensions():
   GLX_ARB_get_proc_address
   GLX_ARB_multisample
   GLX_EXT_visual_info
   GLX_EXT_visual_rating
   GLX_EXT_import_context
   GLX_SGI_video_sync
   GLX_NV_swap_group
   GLX_NV_video_out
   GLX_SGIX_fbconfig
   GLX_SGIX_pbuffer
   GLX_SGI_swap_control
   GLX_EXT_swap_control
   GLX_EXT_swap_control_tear
   GLX_EXT_buffer_age
   GLX_ARB_create_context
   GLX_ARB_create_context_profile
   GLX_NV_float_buffer
   GLX_ARB_fbconfig_float
   GLX_EXT_fbconfig_packed_float
   GLX_EXT_texture_from_pixmap
   GLX_EXT_framebuffer_sRGB
   GLX_NV_present_video
   GLX_NV_copy_image
   GLX_NV_multisample_coverage
   GLX_NV_video_capture
   GLX_EXT_create_context_es_profile
   GLX_EXT_create_context_es2_profile
   GLX_ARB_create_context_robustness
glx_info.get_extensions():
   GLX_EXT_visual_info
   GLX_EXT_visual_rating
   GLX_SGIX_fbconfig
   GLX_SGIX_pbuffer
   GLX_SGI_video_sync
   GLX_SGI_swap_control
   GLX_EXT_swap_control
   GLX_EXT_swap_control_tear
   GLX_EXT_texture_from_pixmap
   GLX_EXT_buffer_age
   GLX_ARB_create_context
   GLX_ARB_create_context_profile
   GLX_EXT_create_context_es_profile
   GLX_EXT_create_context_es2_profile
   GLX_ARB_create_context_robustness
   GLX_ARB_multisample
   GLX_NV_float_buffer
   GLX_ARB_fbconfig_float
   GLX_NV_swap_group
   GLX_EXT_framebuffer_sRGB
   GLX_NV_multisample_coverage
   GLX_NV_copy_image
   GLX_NV_video_capture
   GLX_ARB_get_proc_address

pyglet.media
------------------------------------------------------------------------------
audio driver: <pyglet.media.drivers.openal.OpenALDriver object at 
0x7f8cc3810310>

pyglet.media.avbin
------------------------------------------------------------------------------
AVbin not available.

pyglet.media.drivers.openal
------------------------------------------------------------------------------
Library: <CDLL 'libopenal.so.1', handle 2969450 at 7f8cc186f290>
Version: (1, 1)
Extensions:
Traceback (most recent call last):
  File "/usr/lib/python3.3/site-packages/pyglet/info.py", line 205, in _try_dump
    func()
  File "/usr/lib/python3.3/site-packages/pyglet/info.py", line 183, in dump_al
    for extension in driver.get_extensions():
  File "/usr/lib/python3.3/site-packages/pyglet/media/drivers/openal/__init__.py", line 610, in get_extensions
    return ctypes.cast(extensions, ctypes.c_char_p).value.split(' ')
TypeError: Type str doesn't support the buffer API

pyglet.input.wintab
------------------------------------------------------------------------------
WinTab not available.
AL lib: (EE) alc_cleanup: 2 devices not closed

Original issue reported on code.google.com by Anton.Do...@gmail.com on 26 Feb 2014 at 8:13

GoogleCodeExporter commented 9 years ago
Also, checked the contents of the image data, it's there..

        data = MapToString(data) # modified data, added green line
        for i in range(0,20):
            print(ord(data[i])) # Print some pixels, data verified
        self.texture.format = 'RGBA' # Just to ensure a correct format
        self.texture.set_data('RGBA', tmp.width * 4, data) #Works, renders fine
        self.texture.format = 'RGBA' # Again, ensurance
        self.texture.save('kitten.png') # fully transparent image, no green
        for i in range(0,20): # Verifies data again, yepp still there
            print(ord(self.texture.get_data()[i])) # Note: not 'data' but pixeldata
        self.texture.set_data('RGBA', tmp.width * 4, data) # Now it renders when .draw() EXCEPT for the green line, but the gray square is there.. why?

Original comment by Anton.Do...@gmail.com on 26 Feb 2014 at 8:26

GoogleCodeExporter commented 9 years ago
[deleted comment]
GoogleCodeExporter commented 9 years ago
Here's the entire code (can be run as is, nothing specific to my machine): 
https://gist.github.com/Torxed/a39b6d348757e633f739

Run it with (to generate green line): python3 gen_graph.py 1,5, 11,7 21,15 
31,12 41,1

Original comment by Anton.Do...@gmail.com on 26 Feb 2014 at 8:40

GoogleCodeExporter commented 9 years ago
I tried your example and I got an error: in gen_solid_img, alpha is a float. I 
converted in an integer and I get a kitten.png that I've attached to the but 
report.

Can you tell me if it's the expected result?

I'm using the latest repo code with Python 2.7 in Linux.

Have you look at this? 
http://pyglet.org/doc-current/programming_guide/image.html#saving-an-image

Just to confirm that you have PIL installed :)

Thanks for your report!

Original comment by useboxnet on 26 Feb 2014 at 7:41

Attachments:

GoogleCodeExporter commented 9 years ago
Oh sorry, I didn't run the script correctly. I'm, attaching the result (that I 
think looks OK!).

I have pyllow installed (a PIL-compatible library; python-pillow in Fedora, 
possibly the same name in other distros).

Original comment by useboxnet on 26 Feb 2014 at 7:44

Attachments:

GoogleCodeExporter commented 9 years ago
Ah, I do not have PIL/pillow installed as i was told this was optional. Your 
graph looks perfect, just the way i want it to look like.

Also, yes i used that exact documentation as reference for my code.
I'll install PIL (pillow) tomorrow and rerun the code, but if that fixes 
things.. it shouldn't be to hard to narrow down the issue within the native 
code?

Original comment by Anton.Do...@gmail.com on 26 Feb 2014 at 10:28

GoogleCodeExporter commented 9 years ago
The fallback mechanism is pypng and it doesn't support all type of PNGs when 
saving. The problem here is that it didn't reported an error for you instead of 
generating the wrong image.

Original comment by useboxnet on 27 Feb 2014 at 6:42

GoogleCodeExporter commented 9 years ago
1: Deinstalled everything
2: Installed Python2, code works fine
3: Installed PIL for Python2, code works fine.

4: Deinstalled everything
5: Installed Python3, code does not work.. well it does as long as i don't use 
.save(..) (see the video clip below)
6: Installed Pillow (PIL), still doesn't work.

Here's what happens on my end: https://www.youtube.com/watch?v=I_NwDnkzOhM

Do i need to pass an argument to Pyglet in order for it to choose PIL or is 
that a default override whenever it finds it installed?

Here's what the Python2 output of 'graph.png' looks like both with and without 
PIL.

Original comment by Anton.Do...@gmail.com on 27 Feb 2014 at 10:44

Attachments:

GoogleCodeExporter commented 9 years ago
Great tests, thanks a lot!

Pyglet will automatically use PIL if it's available (I assume you installed PIL 
for Python 3).

Looks to me like this could be an issue with pypng library when working with 
Python 3.

Original comment by useboxnet on 27 Feb 2014 at 10:48

GoogleCodeExporter commented 9 years ago
You're welcome and thank you for taking note of this issue!

I assumed as much since there's no need to use pypng if a superior library is 
present for certain formats. And yepp, python-pillow ("Python Imaging Library 
(PIL) fork. Python3 version.") was installed.

I would assume that pypng ignores PIL in this particular case, but that's just 
my assumption. You have better understanding of the internal mechanics than I 
do so i'll let you work on this on your own :)

Again, thank you for taking a look at this issue! 

Original comment by Anton.Do...@gmail.com on 27 Feb 2014 at 10:51

GoogleCodeExporter commented 9 years ago
Thanks for the follow up!

I knew pillow supports Python 3 (PIL doesn't); it was worth double-checking 
that for you.

The truth is that pypng *actually* supports some encoding cases (not all of 
them though, and I think that's why the docs recommend using PIL).

`save` method has an `encoder` parameter that you can use to specify the exact 
encoder want to use. For example:

from pyglet.image.codecs.png import PNGImageEncoder
encoder = PNGImageEncoder()

And you can use that encoder.

In *.codecs you also have `pil` to test:

from pyglet.image.codecs.pil import PILImageEncoder
encoder = PILImageEncoder()

It would be useful if you could try the encoders in that way so we can identify 
which encoder is not working for you in Python 3.

(I'm writing the code examples here without testing them, you may need to tweak 
them -- sorry abut that!)

Original comment by useboxnet on 27 Feb 2014 at 11:07

GoogleCodeExporter commented 9 years ago
Both encoders were defect. They both produced the same output as shown in the 
video-clip.
Also i tried to do: "from pyglet.image.codecs.pypng import ..." but since i 
didn't know (or find) what to import from it and pass to `encoder=` i had very 
little luck.
I thought of overriding the PIL and `png` libraries with pypng and see if that 
helped.

Here's the code i used:

self.texture.save('graph.png', encoder=PILImageEncoder())
self.texture.save('graph.png', encoder=PNGImageEncoder())

with respective imports ofc.

Original comment by Anton.Do...@gmail.com on 27 Feb 2014 at 12:18

GoogleCodeExporter commented 9 years ago
OK, I finally had time to look at your issue and I think the difference is in 
the behaviour of python 3 regarding the Sprite class. Unfortunately I don't 
have enough knowledge to explain why it happens.

If you save the picture AFTER calling the Sprite __init__ with super, the 
behaviour is exactly like in python 2. My guess is that something needs to be 
initialised in python 3 and not in python 2.

Calling save before the Sprite instance is initialised was the problem. So I 
concur this is not a bug :)

Original comment by useboxnet on 6 Mar 2014 at 8:48

GoogleCodeExporter commented 9 years ago
[deleted comment]
GoogleCodeExporter commented 9 years ago
Almost, i've modified the code so both the `class GUI(pyglet.window.Window)` 
and `class Graph(pyglet.sprite.Sprite)` is initialized properly at the 
rendering function of pyglet.window.Window (`app.run()`) i try to save the 
image, the image is still blank.

Tried with both PIL and without it, and using the latest alpha from Pyglet, 
both compiled on my own so no package manager was used.

Code looks like this:

# GUI() class in the above example
def render(self, *args):
    pyglet.gl.glClearColor(1,1,1,1)
    self.clear()
    self.graphics['Graph'].texture.save('output.png')

It renders beautifully now in Python3, so even tho i try this (which broke 
before), it renders:

# again, GUI() class function
def render(self, *args):
    pyglet.gl.glClearColor(1,1,1,1)
    self.clear()
    test = self.graphics['Graph'].get_image_data()
    test.save('output.png')

Before that would cause a black screen, not it renders at least.. I'm currently 
doing a screen-grab via pyglets internal screen-capture function and that works 
but with the down-side of not being able to set alpha channels (since, the 
background will "block" the transparancy of an object when saving a screenshot).

What code did you use to test this? Because I've moved around `.save()` quite a 
lot and try to figure out where you placed it in order to achieve good results :

Also note that i did try both with and without:

    .save('output.png', encoder=PILImageEncoder|PNGImageEncoder)

Same result. The result is a semi-transparent gray box without any lines in it 
(on disk, on the screen.. it's the same gray box but with lines as well..)

Original comment by Anton.Do...@gmail.com on 7 Mar 2014 at 9:38

GoogleCodeExporter commented 9 years ago
I used the script you linked: 
https://gist.github.com/Torxed/a39b6d348757e633f739

I only had to move the save *after* the super call in Graph __init__ (oh, and 
add a int wrapping 0.2*255 in gen_solid_img).

If I don't change that save to be after the __init__, it won't render even on 
the screen.

Original comment by useboxnet on 7 Mar 2014 at 9:40

GoogleCodeExporter commented 9 years ago
[deleted comment]
GoogleCodeExporter commented 9 years ago
[deleted comment]
GoogleCodeExporter commented 9 years ago
This is the most bizzar phenomenon i've encountered in a few years.
I'm so greatful for all the help you put in to this and i must be annoying as 
hell by now.. But could you explain this for me: 
https://www.youtube.com/watch?v=TPgtT3sQnCk

Python3, PIL (and not, tried both), Pyglet-hg from the repo (not sure how to 
get out the exact rev).. :/

I did try this on two separate machines just to be on the safe side, both gave 
the same result. Debian and ArchLinux respecitvely renders the image+modified 
data perfectly but the saved file doesn't contain the modified data still.

I used the packagemanager on Arch to install Pyglet alpha (from the AUR, called 
pyglet-hg) and compiled it manually on the Debian machine (Python3, 
Python3-dev, pyglet-be521fae6f29, Pillow-2.3.0, gcc Debian 4.7.2-5)

Original comment by Anton.Do...@gmail.com on 7 Mar 2014 at 10:10

GoogleCodeExporter commented 9 years ago
You're welcome, and I'm sorry I can't help you more :)

I think here are two different things: saving before initializing the Sprite 
subclass, that will affect the on screen rendering, and the save itself that I 
must confess got me completely lost (because it works in my system!).

If you got the render working, let's focus on getting the screen saved. This is 
my preferred way of getting a screenshot:

https://github.com/reidrac/pyglet-template/blob/master/game/__init__.py#L147

Basically: pyglet.image.get_buffer_manager().get_color_buffer().save(filename)

I don't know if that's what you're using at the moment.

Also I got to reproduce the "transparent image" issue with python 3.2.3 and 
pypng :) Well, it actually crashes before that because of a different problem 
(not happening with python 3.3!):

Traceback (most recent call last):
  File "t.py", line 198, in <module>
    x.run()
  File "t.py", line 191, in run
    self.render()
  File "t.py", line 166, in render
    self.graphics['Graph'].image.save("output.png")
  File ".../pyglet/_build/lib/pyglet/image/__init__.py", line 453, in save
    encoder.encode(self, file, filename)
  File ".../pyglet/_build/lib/pyglet/image/codecs/png.py", line 103, in encode
    data.fromstring(image.data)
  File ".../pyglet/_build/lib/pyglet/image/__init__.py", line 1149, in _get_data
    rows = re.findall('.' * abs(self._current_pitch), data, re.DOTALL)
  File "/usr/lib/python3.2/re.py", line 193, in findall
    return _compile(pattern, flags).findall(string)
TypeError: can't use a string pattern on a bytes-like object

I'll look at this later because that could be related (I used a cast to string 
in that findall and then I got the transparent image).

Original comment by useboxnet on 7 Mar 2014 at 10:43

GoogleCodeExporter commented 9 years ago
Yea it got me kinda lost when you sad it's working for you.. Spent a few hours 
just fiddling around with different combinations (because to be honest, moving 
.save() after initializing a sprite makes sense sort of so i was thinkin there 
might be some other stuff that i did in "the wrong order".. but out of luck).

I'm using 
`pyglet.image.get_buffer_manager().get_color_buffer().save('graph.png')` as 
well, i digg it and it does 99% of the job at the moment so the people i'm 
generating graphs for are satisfied as long as they don't come up with the 
genious idea that "transparent images are the new", in which case i'm screwed 
unless this issue is resolved :)

That aside, I'm on board that these are two separate issues.
I'll just list the different version of everything (some are repeated from 
above):

Debian:
 - Python 3.2.3 (default, Feb 20 2013, 14:44:27) built with GCC 4.7.2 on Linux2
 - GCC Debian 4.7.2-5
 - Pyglet via http://pyglet.googlecode.com/archive/tip.zip
 - Pillow-2.3.0
 - Python3-dev package for the header files (assuming 3.2.3 is the linkage)

Arch:
 - Python 3.3.4 (default, Feb 11 2014, 15:56:08) built with GCC 4.8.2 20140206 (prerelease) on Linux.
 - GCC 4.8.2 20140206 (prerelease)
 - Pyglet 1.2alpha1.2774.f8da1dcafc85-1 (via hg clone https://pyglet.googlecode.com/hg)
 - Pillow 2.3.0-3 (Patches: https://projects.archlinux.org/svntogit/community.git/log/trunk?h=packages/python-pillow)

It's strange because i did not recieve that error when running on my debian box 
(3.2.3), and i think i'm using pypng sinde i didn't have pillow installed at 
first :/

Original comment by Anton.Do...@gmail.com on 7 Mar 2014 at 10:59

GoogleCodeExporter commented 9 years ago
Well, it works for me with python 3.3.2, but not with python 3.2.3. Not all 
python 3 versions are the same! :)

I'll investigate further now that I have a clue! Thanks again for your report.

Original comment by useboxnet on 7 Mar 2014 at 11:15

GoogleCodeExporter commented 9 years ago
[deleted comment]
GoogleCodeExporter commented 9 years ago
Thank you, I really hope you find something.
I'll do a stack-trace of the 3 different python versions and see if i find 
anything.. Should be able to figure out something by doing: python -m trace 
--trace test.py

Anyway, i installed Python3.2.3-2 as well just for the kicks, same issue.
But i'll let you figure out what's wrong without me putting ideas in your head, 
but if you need more info just poke and i'll do what i can..

Thank you in advance! :)

Original comment by Anton.Do...@gmail.com on 7 Mar 2014 at 11:35

GoogleCodeExporter commented 9 years ago
I updated the gist with a  print('---- BEGIN') and a print('END ----'), i then 
ran a trace:

    python -m trace --trace test.py

I know it's hughe, but you could run the same and do a diff on my attached file.
Note that the file will be hughe, so i cropped it down to just right before 
'---- BEGIN' and cropped the *hughe* repetative pattern that looked like:

    compat.py(75):             return bytes(ord(c) for c in s)
     --- modulename: compat, funcname: <genexpr>

Think it repeated a few million times.. So i cropped it down to 3 times + the 2 
initial compat.py and a trailing one without the ---- stuff.:

    compat.py(72):         if isinstance(s, bytes):
    compat.py(74):         elif isinstance(s, str):
    compat.py(75):             return bytes(ord(c) for c in s)
     --- modulename: compat, funcname: <genexpr>
    compat.py(75):             return bytes(ord(c) for c in s)
     --- modulename: compat, funcname: <genexpr>
    compat.py(75):             return bytes(ord(c) for c in s)
     --- modulename: compat, funcname: <genexpr>
    compat.py(75):             return bytes(ord(c) for c in s)

Original comment by Anton.Do...@gmail.com on 7 Mar 2014 at 11:46

Attachments:

GoogleCodeExporter commented 9 years ago
Crap, full command when traced was:

    python -m trace --trace test.py 10,20, 20,30 > debug.log

You'll need that in order to simulate the exact number of operations for 
certain calculations i guess. So use that.

do a:

    diff debug.log py334-debug.log

You should be able to figure out what is happening in your machine which 
differs from mine when executing the same code on the same python version and 
on different..
I'll throw in a 3.2.3 trace as well in this post, because they should be 100% 
similar.

And yes pypng is used :)

    pypng.py(243):         outfile.write(struct.pack("!I", len(data)))
    pypng.py(244):         outfile.write(tag)
    pypng.py(245):         outfile.write(data)
    pypng.py(246):         checksum = zlib.crc32(tag)
    pypng.py(247):         checksum = zlib.crc32(data, checksum)

etc..

Original comment by Anton.Do...@gmail.com on 7 Mar 2014 at 11:55

Attachments:

GoogleCodeExporter commented 9 years ago
On a side note: In Py3, poking around with *ANY* value inherited from pyglet 
before __init__ has been called on the pyglet object will break the appliction.

Tried setting `self.x = ...` before initializing pyglet.sprite.Sprite and i got:

      File "/usr/lib/python3.3/site-packages/pyglet/sprite.py", line 459, in _set_x
        self._update_position()
      File "/usr/lib/python3.3/site-packages/pyglet/sprite.py", line 393, in _update_position
        img = self._texture
    AttributeError: 'Grass' object has no attribute '_texture'

This must have something to do with how Python3 vs Python2 initializes classes 
because for instance, in Python3 i can do:

    class Grass(BasicObject):
        def __init__(*args, **dictWars):
            ## If we are inherited from another class,
            ## the arguments will be passed only into *args and we
            ## need to unpack them outselves if 4 conditions are met
            ## that can only happen if we are inherited.
            if type(args) == tuple and len(args) == 2 and len(dictWars) == 0 and type(args[1]) == dict:
                args, dictWars = args
            self = args[0]
            BasicObject.__init__(args, dictWars)

While in Python2 this would give me:

        BasicObject.__init__(args, dictWars)
    TypeError: unbound method __init__() must be called with BasicObject instance as first argument (got tuple instance instead)

I know this is a weird fucking thing to do when initializing classes, but it 
works like a swizz clockwork in Py3 and gives me insane control over the 
structure of a class and passing arguments can be done transparently throughout 
multiple inherits in such a dynamic way i'm sold on this method :P

Anyway, in Python2 I get the feeling that something is pre-initialized compared 
to Python3..
as if this is the model and it fucks things up:

    class x():
        test = 1
        def __init__(self):
            pass

vs

    class x():
        def __init__(self):
            self.test = 1

They produce the same outcome but in different execution orders when inheriting 
objects.. or at least that's the feeling i get :/
A small side-note to the original problem of why the rendering issue makes 
sense.. still doesn't solve my .save() issue :)

Original comment by Anton.Do...@gmail.com on 8 Mar 2014 at 10:48