PIL 中超大图处理 索引格式PNG合并问题

49 views
Skip to first unread message

可可熊

unread,
Jul 29, 2009, 10:36:17 PM7/29/09
to python-cn`CPyUG`华蟒用户组
关于PIL使用中几个问题:

一、PIL中如果使用Image.new("RGB",(x,y))生成图片的话 会占用很大的内存(x*y*4
bytes),如果图片分辨率较大new调用会出现MemoryError错误,那么如何用PIL 创建一个超大分辨率的图片(如(1024*40,
1024*40)

二、有两个索引格式 (PIL中的'P'模式) 的PNG图片,分别有各自的palette,怎么把这两个图片合并成一个索引格式的图片呢

有一种办法是先新建一个’RGB‘模式的图片,然后分别把两张图片粘进来,最后再把这个’RGB‘转换为'P',不过这样做有一个问题,新建一个'RGB'模式的图片会战用4倍于
'P' 模式图片的内存。

三、如何把N个小图片合并成一个大图片。

一种方法是先新建一个(x,y)大小的图片,然后再把小图片一个一个的粘进去,那么在这个过程中,内存的占用一直是x*y*4
bytes,如果图片较多,合并的图片过大,那么内存占用会一直很大。

另一种方法,把要分块把要合并的小图片合并,比如一个8x8的大图,可以先创建1x8的图片,然后把这个图片用小图添满,保存到硬盘,依次进行。这样内存的占用会减少很多,只有在最后一步把8个图片合并时才会占用到和第一种方法一样大小的内存,不过这个时间就减少了很多。

有没有更好的办法呢?

Heroboy

unread,
Jul 29, 2009, 10:51:36 PM7/29/09
to pyth...@googlegroups.com
加内存



可可熊

unread,
Jul 29, 2009, 11:23:04 PM7/29/09
to pyth...@googlegroups.com
2009/7/30 Heroboy <yangw...@gmail.com>:
>
>
> 2009/7/30 可可熊 <cocob...@gmail.com>

那么你要处理一个(1024*40, 1024*40)的图片就去加64G的内存?


>>
>
>
> >
>

Heroboy

unread,
Jul 29, 2009, 11:33:32 PM7/29/09
to pyth...@googlegroups.com
那么大的图片,不加内存估计没有一个软件能打开。


>>
>
>
> >
>



可可熊

unread,
Jul 30, 2009, 12:06:28 AM7/30/09
to pyth...@googlegroups.com
2009/7/30 Heroboy <yangw...@gmail.com>:
>
>
> 2009/7/30 可可熊 <cocob...@gmail.com>
>>
>> 2009/7/30 Heroboy <yangw...@gmail.com>:
>> >
>> >
>> > 2009/7/30 可可熊 <cocob...@gmail.com>

>> >>
>> >> 关于PIL使用中几个问题:
>> >>
>> >> 一、PIL中如果使用Image.new("RGB",(x,y))生成图片的话 会占用很大的内存(x*y*4
>> >> bytes),如果图片分辨率较大new调用会出现MemoryError错误,那么如何用PIL 创建一个超大分辨率的图片(如(1024*40,
>> >> 1024*40)
>> >>
>> >> 二、有两个索引格式 (PIL中的'P'模式) 的PNG图片,分别有各自的palette,怎么把这两个图片合并成一个索引格式的图片呢
>> >>
>> >>
>> >>
>> >> 有一种办法是先新建一个'RGB'模式的图片,然后分别把两张图片粘进来,最后再把这个'RGB'转换为'P',不过这样做有一个问题,新建一个'RGB'模式的图片会战用4倍于
>> >> 'P' 模式图片的内存。
>> >>
>> >> 三、如何把N个小图片合并成一个大图片。
>> >>
>> >> 一种方法是先新建一个(x,y)大小的图片,然后再把小图片一个一个的粘进去,那么在这个过程中,内存的占用一直是x*y*4
>> >> bytes,如果图片较多,合并的图片过大,那么内存占用会一直很大。
>> >>
>> >>
>> >>
>> >> 另一种方法,把要分块把要合并的小图片合并,比如一个8x8的大图,可以先创建1x8的图片,然后把这个图片用小图添满,保存到硬盘,依次进行。这样内存的占用会减少很多,只有在最后一步把8个图片合并时才会占用到和第一种方法一样大小的内存,不过这个时间就减少了很多。
>> >>
>> >> 有没有更好的办法呢?
>> >
>> > 加内存
>> >>
>>
>> 那么你要处理一个(1024*40, 1024*40)的图片就去加64G的内存?
>

这里写错了,是6.4G


> 那么大的图片,不加内存估计没有一个软件能打开。
>>

那工程建筑上肯定有超大的图片,难道只是加内存?


>>
>> >>
>> >
>> >
>> > >
>> >
>>
>>
>
>
> >
>

Heroboy

unread,
Jul 30, 2009, 12:25:18 AM7/30/09
to pyth...@googlegroups.com
不用加,因为已经有64G内存了。


>>
>> >>
>> >
>> >
>> > >
>> >
>>
>>
>
>
> >
>



可可熊

unread,
Jul 31, 2009, 12:15:39 AM7/31/09
to pyth...@googlegroups.com
2009/7/30 Heroboy <yangw...@gmail.com>:
>
>
> 2009/7/30 可可熊 <cocob...@gmail.com>
>>
>> 2009/7/30 Heroboy <yangw...@gmail.com>:
>> >
>> >
>> > 2009/7/30 可可熊 <cocob...@gmail.com>
>> >>
>> >> 2009/7/30 Heroboy <yangw...@gmail.com>:
>> >> >
>> >> >
>> >> > 2009/7/30 可可熊 <cocob...@gmail.com>

>> >> >>
>> >> >> 关于PIL使用中几个问题:
>> >> >>
>> >> >> 一、PIL中如果使用Image.new("RGB",(x,y))生成图片的话 会占用很大的内存(x*y*4
>> >> >> bytes),如果图片分辨率较大new调用会出现MemoryError错误,那么如何用PIL
>> >> >> 创建一个超大分辨率的图片(如(1024*40,
>> >> >> 1024*40)
>> >> >>
>> >> >> 二、有两个索引格式 (PIL中的'P'模式) 的PNG图片,分别有各自的palette,怎么把这两个图片合并成一个索引格式的图片呢
>> >> >>
>> >> >>
>> >> >>
>> >> >>
>> >> >> 有一种办法是先新建一个'RGB'模式的图片,然后分别把两张图片粘进来,最后再把这个'RGB'转换为'P',不过这样做有一个问题,新建一个'RGB'模式的图片会战用4倍于
>> >> >> 'P' 模式图片的内存。
>> >> >>
>> >> >> 三、如何把N个小图片合并成一个大图片。
>> >> >>
>> >> >> 一种方法是先新建一个(x,y)大小的图片,然后再把小图片一个一个的粘进去,那么在这个过程中,内存的占用一直是x*y*4
>> >> >> bytes,如果图片较多,合并的图片过大,那么内存占用会一直很大。
>> >> >>
>> >> >>
>> >> >>
>> >> >>
>> >> >> 另一种方法,把要分块把要合并的小图片合并,比如一个8x8的大图,可以先创建1x8的图片,然后把这个图片用小图添满,保存到硬盘,依次进行。这样内存的占用会减少很多,只有在最后一步把8个图片合并时才会占用到和第一种方法一样大小的内存,不过这个时间就减少了很多。
>> >> >>
>> >> >> 有没有更好的办法呢?
>> >> >


几个问题呢,没人理啊?

ubunoon

unread,
Jul 31, 2009, 12:56:40 AM7/31/09
to pyth...@googlegroups.com
用来创建这么大的图片,我想应该需要特殊处理,一般性的处理PIL也许可以承受,6.4GB的内存,你想要配置什么样的硬件来处理。

图片是具有图片格式的,那么大的图片,我想还是应该通过了解图片格式进行遍历处理。

C语言应该可以处理(但也需要系统的虚拟内存映射,不知道系统支持不支持这么大的文件,似乎可以的)。
--
To be pythoner
My blog: http://www.cnblogs.com/ubunoon/

ubunoon

unread,
Jul 31, 2009, 1:08:11 AM7/31/09
to pyth...@googlegroups.com
你也可以自己创建一个Bitmap的类格式,仅用来至支持头和一小部分数据缓冲,那么大文件,通过这个类缓冲来支持,速度上会慢一些,如果python系统支持读取大文件,read的时候先定位,在读取合理大小的部分,那么应该是不成问题的。可以通过PIL的fromstring来构建另外一个PIL可以操作的bitmap,操作完毕后再转到Bitmap中。也就是常用的双缓冲吧。

只要python系统支持读取那么大的文件,那么这个方法应该是可以的。

可可熊

unread,
Jul 31, 2009, 2:05:54 AM7/31/09
to pyth...@googlegroups.com
2009/7/31 ubunoon <net...@gmail.com>:

> 你也可以自己创建一个Bitmap的类格式,仅用来至支持头和一小部分数据缓冲,那么大文件,通过这个类缓冲来支持,速度上会慢一些,如果python系统支持读取大文件,read的时候先定位,在读取合理大小的部分,那么应该是不成问题的。可以通过PIL的fromstring来构建另外一个PIL可以操作的bitmap,操作完毕后再转到Bitmap中。也就是常用的双缓冲吧。
> 只要python系统支持读取那么大的文件,那么这个方法应该是可以的。
>


不太理解你的做法。

比如我的第一个问题,怎么能解决呢?

BTW:pythoner是不是应该是pythonor :-)


>
> 2009/7/31 可可熊 <cocob...@gmail.com>
>>
>> 2009/7/30 Heroboy <yangw...@gmail.com>:
>> >
>> >
>> > 2009/7/30 可可熊 <cocob...@gmail.com>
>> >>
>> >> 2009/7/30 Heroboy <yangw...@gmail.com>:
>> >> >
>> >> >
>> >> > 2009/7/30 可可熊 <cocob...@gmail.com>
>> >> >>
>> >> >> 2009/7/30 Heroboy <yangw...@gmail.com>:
>> >> >> >
>> >> >> >
>> >> >> > 2009/7/30 可可熊 <cocob...@gmail.com>

Heroboy

unread,
Jul 31, 2009, 3:57:35 AM7/31/09
to pyth...@googlegroups.com
2009/7/31 可可熊 <cocobear.cn@gmail.com>
2009/7/31 ubunoon <net...@gmail.com>:
> 你也可以自己创建一个Bitmap的类格式,仅用来至支持头和一小部分数据缓冲,那么大文件,通过这个类缓冲来支持,速度上会慢一些,如果python系统支持读取大文件,read的时候先定位,在读取合理大小的部分,那么应该是不成问题的。可以通过PIL的fromstring来构建另外一个PIL可以操作的bitmap,操作完毕后再转到Bitmap中。也就是常用的双缓冲吧。
> 只要python系统支持读取那么大的文件,那么这个方法应该是可以的。
>


不太理解你的做法。

比如我的第一个问题,怎么能解决呢?

BTW:pythoner是不是应该是pythonor :-)
加内存,放弃pil,辞职

可可熊

unread,
Jul 31, 2009, 5:10:12 AM7/31/09
to pyth...@googlegroups.com
2009/7/31 Heroboy <yangw...@gmail.com>:
>
>
> 2009/7/31 可可熊 <cocob...@gmail.com>

>>
>> 2009/7/31 ubunoon <net...@gmail.com>:
>> >
>> > 你也可以自己创建一个Bitmap的类格式,仅用来至支持头和一小部分数据缓冲,那么大文件,通过这个类缓冲来支持,速度上会慢一些,如果python系统支持读取大文件,read的时候先定位,在读取合理大小的部分,那么应该是不成问题的。可以通过PIL的fromstring来构建另外一个PIL可以操作的bitmap,操作完毕后再转到Bitmap中。也就是常用的双缓冲吧。
>> > 只要python系统支持读取那么大的文件,那么这个方法应该是可以的。
>> >
>>
>>
>> 不太理解你的做法。
>>
>> 比如我的第一个问题,怎么能解决呢?
>>
>> BTW:pythoner是不是应该是pythonor :-)
>
> 加内存,放弃pil,辞职


呵呵也用不着辞职 自己玩玩。


>>
>>
>> >
>> > 2009/7/31 可可熊 <cocob...@gmail.com>
>> >>
>> >> 2009/7/30 Heroboy <yangw...@gmail.com>:
>> >> >
>> >> >
>> >> > 2009/7/30 可可熊 <cocob...@gmail.com>
>> >> >>
>> >> >> 2009/7/30 Heroboy <yangw...@gmail.com>:
>> >> >> >
>> >> >> >
>> >> >> > 2009/7/30 可可熊 <cocob...@gmail.com>
>> >> >> >>
>> >> >> >> 2009/7/30 Heroboy <yangw...@gmail.com>:
>> >> >> >> >
>> >> >> >> >
>> >> >> >> > 2009/7/30 可可熊 <cocob...@gmail.com>

Joseph Qu

unread,
Jul 31, 2009, 2:44:59 PM7/31/09
to pyth...@googlegroups.com
PIL 没研究。
不过假设你只是显示,或者局部操作。只需要在内存中常驻一小部分。

可以参照Proxy模式。实现代理,缩小常驻内存的消耗。

ubunoon

unread,
Aug 5, 2009, 7:56:26 AM8/5/09
to pyth...@googlegroups.com
Joseph Qu的已经说的很明白了,局部操作,要操作的那一部分拿出来,完事了,放到文件中,用一个文件索引指针来表示你当前操作的方式。

Proxy模式起初就是用来处理大量图片的显示问题。


2009/8/1 Joseph Qu <ace...@gmail.com>

cocobear

unread,
Aug 5, 2009, 10:01:09 PM8/5/09
to python-cn`CPyUG`华蟒用户组(中文Py用户组)

On 8月5日, 下午7时56分, ubunoon <net...@gmail.com> wrote:
> Joseph Qu的已经说的很明白了,局部操作,要操作的那一部分拿出来,完事了,放到文件中,用一个文件索引指针来表示你当前操作的方式。
> Proxy模式起初就是用来处理大量图片的显示问题。
>

问题是我怎么能先生成一个大图像。


> 2009/8/1 Joseph Qu <ace...@gmail.com>
>
>
>
>
>
> > PIL 没研究。不过假设你只是显示,或者局部操作。只需要在内存中常驻一小部分。
>
> > 可以参照Proxy模式。实现代理,缩小常驻内存的消耗。
>

> > 2009/7/31 可可熊 <cocobear...@gmail.com>
>
> >> 2009/7/31 Heroboy <yangwei...@gmail.com>:
>
> >> > 2009/7/31 可可熊 <cocobear...@gmail.com>
>
> >> >> 2009/7/31 ubunoon <net...@gmail.com>:
>
> >> 你也可以自己创建一个Bitmap的类格式,仅用来至支持头和一小部分数据缓冲,那么大文件,通过这个类缓冲来支持,速度上会慢一些,如果python系统支持 读取大文件,read的时候先定位,在读取合理大小的部分,那么应该是不成问题的。可以通过PIL的fromstring来构建另外一个PIL可以操作的bit map,操作完毕后再转到Bitmap中。也就是常用的双缓冲吧。


> >> >> > 只要python系统支持读取那么大的文件,那么这个方法应该是可以的。
>
> >> >> 不太理解你的做法。
>
> >> >> 比如我的第一个问题,怎么能解决呢?
>
> >> >> BTW:pythoner是不是应该是pythonor :-)
>
> >> > 加内存,放弃pil,辞职
>
> >> 呵呵也用不着辞职 自己玩玩。
>

> >> >> > 2009/7/31 可可熊 <cocobear...@gmail.com>
>
> >> >> >> 2009/7/30 Heroboy <yangwei...@gmail.com>:
>
> >> >> >> > 2009/7/30 可可熊 <cocobear...@gmail.com>
>
> >> >> >> >> 2009/7/30 Heroboy <yangwei...@gmail.com>:
>
> >> >> >> >> > 2009/7/30 可可熊 <cocobear...@gmail.com>
>
> >> >> >> >> >> 2009/7/30 Heroboy <yangwei...@gmail.com>:
>
> >> >> >> >> >> > 2009/7/30 可可熊 <cocobear...@gmail.com>


>
> >> >> >> >> >> >> 关于PIL使用中几个问题:
>
> >> >> >> >> >> >> 一、PIL中如果使用Image.new("RGB",(x,y))生成图片的话 会占用很大的内存(x*y*4
> >> >> >> >> >> >> bytes),如果图片分辨率较大new调用会出现MemoryError错误,那么如何用PIL
> >> >> >> >> >> >> 创建一个超大分辨率的图片(如(1024*40,
> >> >> >> >> >> >> 1024*40)
>
> >> >> >> >> >> >> 二、有两个索引格式 (PIL中的'P'模式)
> >> >> >> >> >> >> 的PNG图片,分别有各自的palette,怎么把这两个图片合并成一个索引格式的图片呢
>
> >> 有一种办法是先新建一个'RGB'模式的图片,然后分别把两张图片粘进来,最后再把这个'RGB'转换为'P',不过这样做有一个问题,新建一个'RGB'模式 的图片会战用4倍于
> >> >> >> >> >> >> 'P' 模式图片的内存。
>
> >> >> >> >> >> >> 三、如何把N个小图片合并成一个大图片。
>
> >> 一种方法是先新建一个(x,y)大小的图片,然后再把小图片一个一个的粘进去,那么在这个过程中,内存的占用一直是x*y*4
> >> >> >> >> >> >> bytes,如果图片较多,合并的图片过大,那么内存占用会一直很大。
>

> >> 另一种方法,把要分块把要合并的小图片合并,比如一个8x8的大图,可以先创建1x8的图片,然后把这个图片用小图添满,保存到硬盘,依次进行。这样内存的占用 会减少很多,只有在最后一步把8个图片合并时才会占用到和第一种方法一样大小的内存,不过这个时间就减少了很多。

ubunoon

unread,
Aug 6, 2009, 1:29:20 AM8/6/09
to pyth...@googlegroups.com
直接读写文件,不用PIL方式写文件

file = open(picturefile, "wb")
file.write ( struct.packle( fileheader ) )
file.write( picturedata )
file.close()

虽然如此可以读写文件,不建议将这么大的一个图片放在一个文件中,可以分开放在多个文件中,然后自己进行组织,那样或许更有效,出现错误也更容易被修复,你的要求特殊,就应该自己写特殊的处理方式,而不应该采用PIL的处理方式。
Reply all
Reply to author
Forward
0 new messages