はてなキーワード: mmapとは
僕はプログラミング歴2週間の初心者です。キーと値を入力できるデータベースを作っています。
以下のコードを実行してデータを追加し続けると、一定のサイズを超えるとエラーが出てしまうみたいです。
理想は、データが追加された後にサイズが足りなくなったら動的に自動拡大されることです。
もし詳しい人がいたらご教示お願い致します。
import sys import os import mmap import hashlib def h(x): return int(hashlib.sha512(x.encode()).hexdigest(), 16) def create_db(filename): with open(filename, 'wb') as f: f.write(b'\0' * 1024 * 1024) # 1MBの空ファイルを作成 def set_key(filename, key, value): with open(filename, 'r+b') as f: mm = mmap.mmap(f.fileno(), 0) pos = h(key) % mm.size() while mm[pos:pos+1] != b'\0': pos = (pos + 1) % mm.size() if pos == h(key) % mm.size(): f.seek(0, os.SEEK_END) f.write(b'\0' * mm.size()) # ファイルサイズを2倍にする mm = mmap.mmap(f.fileno(), f.tell()) # ファイルサイズを反映させる pos = h(key) % mm.size() # ハッシュ値を再計算する data = key + '\0' + value + '\0' data = data.encode() mm[pos:pos+len(data)] = data mm.close() # mmapオブジェクトを閉じる def get_key(filename, key): with open(filename, 'r+b') as f: mm = mmap.mmap(f.fileno(), 0) pos = h(key) % mm.size() while mm[pos:pos+1] != b'\0': end = mm.find(b'\0', pos, mm.size()) # 第2引数と第3引数を指定する if end == -1: end = mm.size() if mm[pos:end].decode() == key: pos = end + 1 end = mm.find(b'\0', pos, mm.size()) # 第2引数と第3引数を指定する if end == -1: end = mm.size() value = mm[pos:end].decode() mm.close() # mmapオブジェクトを閉じる return value pos = (pos + 1) % mm.size() if pos == h(key) % mm.size(): break mm.close() # mmapオブジェクトを閉じる return None def main(): cmd = sys.argv[1] if cmd == 'create': create_db(sys.argv[2]) elif cmd == 'set': set_key(sys.argv[2], sys.argv[3], sys.argv[4]) elif cmd == 'get': print(get_key(sys.argv[2], sys.argv[3])) if __name__ == '__main__': main()
Photoshopのタイル構造はどのように実装したら良いですか?何か参考になるソースコードなどはありませんか?
Photoshopのタイル構造は、画像を小さな矩形のブロックに分割して、各ブロックを個別に処理することで実現されます。これにより、大きな画像の処理を高速化することができます。
このアルゴリズムを実装するには、以下のような手順が必要になります。
画像を読み込む
処理が完了したら、結果を保存する
以下は、Pythonで実装された簡単なタイル構造のコード例です。この例では、画像を単純にグレースケール化しています。
import numpy as np from PIL import Image # 画像を読み込む im = Image.open("input.jpg") # タイルのサイズを決定する tile_size = 128 # 画像をタイルに分割する tiles = [] width, height = im.size for y in range(0, height, tile_size): for x in range(0, width, tile_size): box = (x, y, x + tile_size, y + tile_size) tile = im.crop(box) tiles.append(tile) # 各タイルを個別に処理する for i, tile in enumerate(tiles): tile = tile.convert("L") tiles[i] = tile # 処理されたタイルを結合して、元の画像を再構築する output = Image.new("L", (width, height)) x = 0 y = 0 for i, tile in enumerate(tiles): output.paste(tile, (x, y)) x += tile_size if x >= width: x = 0 y += tile_size # 結果を保存する output.save("output.jpg")
このコードは、Pillowを使用して、画像の読み込み、タイルの分割、処理されたタイルの結合、結果の保存を行っています。このコードを改良することで、より高度な画像処理アルゴリズムを実装することができます。
回答ありがとうございます。しかし、実際にはこれに拡大縮小、タイルを跨いでのコピー&ペースト、ペンツールでの描画などが加わります。拡大縮小は画像ピラミッドのようなもの、メモリ以上の巨大な画像を扱えるのはmmapを使っているのではないかと予想しています。これらを一言で回答するのは難しいと思いますが、何かアドバイスをいただけないでしょうか。よろしくお願いいたします。
拡大縮小、タイルを跨いでのコピー&ペースト、ペンツールでの描画などを実装するためには、より高度なアルゴリズムとテクニックが必要になります。
拡大縮小に関しては、画像ピラミッドを使用することで実現できます。画像ピラミッドは、複数の解像度レベルで同じ画像を表現する方法です。画像ピラミッドを使用することで、拡大縮小のプロセスを簡単かつ高速に行うことができます。OpenCVやPillowなどのライブラリは、画像ピラミッドを構築するための機能を提供しています。
タイルを跨いでのコピー&ペーストは、オーバーレイ技術を使用することで実現できます。オーバーレイとは、複数の画像を重ね合わせることで、新しい画像を生成する技術です。タイルを跨いでのコピー&ペーストは、オーバーレイを使用して、複数のタイルを重ね合わせることで実現できます。また、透明度を使用することで、重ね合わせたタイルの一部を透明にすることもできます。
ペンツールでの描画に関しては、画像のピクセル単位での操作が必要になります。これは、OpenCVやPillowなどの画像処理ライブラリを使用して実現できます。画像のピクセル単位での操作には、色の変更、描画、消去などが含まれます。これらの操作を組み合わせることで、複雑な描画機能を実現することができます。
最後に、メモリ以上の巨大な画像を扱うために、mmapを使用することは可能です。mmapを使用することで、ファイルをメモリ上にマップし、ファイルと同じようにアクセスすることができます。これにより、ファイルがメモリに収まらない場合でも、ファイルの一部をメモリにマップし、必要な部分だけを読み書きすることができます。ただし、mmapを使用する場合は、適切なメモリ管理が必要であり、オーバーヘッドが発生する可能性があるため、十分なテストと調整が必要です。