Djangoの画像に視覚効果を適用する

私自身の「インスタグラム」を書くとき、アップロード中に画像にフィルターをかける必要がありました。 最初は、サーバーを特にロードしないために、イメージを変換するプロセスをクライアント側に転送することが決定されました。 主なアイデアは、画像をキャンバスにアップロードし、それを操作して、バイトストリーム(結果の画像)をサーバーにアップロードすることです。 実装のために、 CamanJS jsライブラリが選択されました。これは、ブラウザとNodeJSを介したサーバー側の両方で機能します。 しかし、私は3つの理由でそれを放棄しなければなりませんでした:





次に、サーバー側でCamanJSを使用しようとしました。 結果は再び不満足でした:





その結果、CamanJSを完全に放棄しなければなりませんでした。



サーバー側で画像を処理するための最も最適なオプションは、 ImageMagickソフトウェアパッケージでした。このパッケージはかなり豊富な機能を備えており、さまざまなプログラミング言語の多くの拡張機能を備えています。 このプロジェクトはdjangoで動作するため、主にImageMagickのPython拡張機能であるPythonMagickとWandaに興味がありました。 判明したように、ImageMagickのすべての機能をサポートしているわけではなく、グラフィック効果の一部が欠落しているため、サブプロセスを介してimagemagickを直接呼び出しました。

効果は、非常に有用なリソースhttp://www.fmwconcepts.com/imagemagickを使用して取得された特別なbashスクリプトを介して適用されます。ここに、スクリプト自体とその説明、 http://jqmagick.imagemagick.orgがあります。さまざまな効果とオプションを選択します。



まず、 http://jqmagick.imagemagick.orgにアクセスして、写真をアップロードし、目的の効果を選択し、そのパラメーターを選択します。 すべてが美しく、すべてが私たちに合っている場合は、サンプルコマンドをコピーして、「options」セクションの下部フィールド(デフォルトではjqmagickインターフェースの右下部分)から必要なパラメーターを使用してスクリプトを実行します。 例:



bash scripts/vintage1.sh -b 0 -c 35 -s roundrectangle -T torn -I grunge -C white output/8526-603.jpg output/3347-9458.jpg
      
      







興味のあるスクリプトはvintage1.shと呼ばれます。 http://www.fmwconcepts.com/imagemagickに移動し、必要なスクリプトを見つけてダウンロードし、「実行」ボックスをチェックすることを忘れないでください。 このようにして、必要なすべての効果を選択します。

これで、ソフトウェア実装の準備がすべて整いました。



したがって、タスク:



ユーザー(この場合、ユニークな商品を販売するeコマースプラットフォームの売り手)がサーバーに画像をアップロードできるようにするには、結果を表示する機能を備えた事前に準備されたセットからユーザーに効果を適用します



サーバーに画像をアップロードする



画像をサーバーにアップロードするために、 filereader.js jsライブラリーを使用しました 。 使用法と構成の例は、このライブラリの仕様に記載されています。 ファイルがブラウザーのFileReaderオブジェクトに完全にアップロードされた後、XMLHttpRequestオブジェクトのsend()メソッドを使用して、サーバーへのファイルの直接送信を実装しました。 これを行うには、オプション「load」を定義します。



 var opts = { // … load: function(e, file) { var xhr = new XMLHttpRequest(); xhr.open('POST', '{% url upload_file %}', true); xhr.onload = function() { if (this.status == 200) { //        var resp = JSON.parse(this.response); //        (    ) filter_image = resp['image']; filter_thumb = resp['thumb']; } }; xhr.send(file); }, //… };
      
      







サーバーで、アップロードされた画像を受け入れ、プレビュー用のコピーを作成し、元の画像の名前とプレビューの名前をクライアントに返し、プレビューの要素のsrc属性を入力します。



 import os import datetime from PIL import Image try: from cStringIO import StringIO except ImportError: from StringIO import StringIO import simplejson as json from django.http import HttpResponse from django.conf import settings def upload_file(request): max_size = (2560, 2048) #      thumb_size = (325, 325) #     f_data = request.body fake_file = StringIO() fake_file.write(f_data) fake_file.seek(0) img = Image.open(fake_file) img.thumbnail(max_size, Image.ANTIALIAS) #     tmp_dir = settings.TEMP_IMG_DIR #         if not os.path.exists(tmp_dir): os.makedirs(tmp_dir) #        inner_dir_name = datetime.datetime.now().strftime('%d.%m.%Y') inner_dir = os.path.abspath(os.path.join(tmp_dir, inner_dir_name)) if not os.path.exists(inner_dir): os.makedirs(inner_dir) tmp_file_name = generate_tmp_file_name() #      thumb_tmp_file_name = 'thumb_' + tmp_file_name #     output = os.path.abspath(os.path.join(inner_dir, tmp_file_name)) output_thumb = os.path.abspath(os.path.join(inner_dir, thumb_tmp_file_name)) if not img.mode == 'RGB': img = img.convert('RGB') img.save(output, "JPEG") #      jpeg    img.thumbnail(thumb_size, Image.ANTIALIAS) img.save(output_thumb, "JPEG") #     to_response = json.dumps({ 'image': ''.join([settings.MEDIA_URL, '/'.join([settings.TEMP_IMG_DIR_NAME, innder_dir_name, tmp_file_name])]), 'thumb': ''.join([settings.MEDIA_URL, '/'.join([settings.TEMP_IMG_DIR_NAME, innder_dir_name, thumb_tmp_file_name])]), }) return HttpResponse(to_response, mimetype="application/json")
      
      







setting.pyのTEMP_IMG_DIR自体は、次のように定義されています。



 #      TEMP_IMG_DIR = os.path.abspath(os.path.join(MEDIA_ROOT, 'temp_img'))
      
      







画像に効果を適用する



ここでの主なアイデアは、効果は元の画像ではなくプレビューに適用され、「保存」ボタンを最後にクリックした後にのみ選択された効果が画像自体に適用されるということです。

クライアント側で効果を適用する機能:



 function setFilter(filter_name) { result_filter = filter_name $.ajax({ url: '{% url set_filter %}', method: 'POST', data: { 'img_path': filter_thumb, //     'filter_name': filter_name //    }, success: function(response) { $('#result_img').attr('src', response); //   } }) }
      
      







サーバー側では、エフェクトを適用するためのコマンドを決定し、それらをフィルターの名前と比較します;ここでは辞書を使用すると便利です:



 FILTERS_COMMAND = { 'f1': "bash_scripts/colortemp.sh -t 10950 {file_name} {output}", 'f2': "bash_scripts/colortemp.sh -t 5736 {file_name} {output}", # … 'f8': "bash_scripts/colorfilter.sh -c sepia -m 1 -d 28 {file_name} {output}", 'f9': "bash_scripts/colorfilter.sh -c underwater -m 1 -d 20 {file_name} {output}" }
      
      







サーバー副作用機能:



 import os import sys import subprocess def apply_filter(img_path, filter_name, output=None): if output is None: output_file_name = ''.join([filter_name, '_', os.path.basename(img_path)]) output_file = os.path.abspath(os.path.join(img_path.replace(os.path.basename(img_path), ''), output_file_name)) if os.path.exists(output_file): return output_file else: output_file = output command = FILTERS_COMMAND[filter_name] #  bash,  ,     : command = command.replace('(', '\(').replace(')', '\)') command = command.format(file_name=img_path, output=output_file) subprocess.check_output(command, shell=True, stderr=subprocess.STDOUT) return output_file
      
      







apply_filter関数はset_filterハンドラーを呼び出します。このハンドラーは2つの引数を取ります。画像へのパスとフィルターの名前で、変更された画像へのパスを返します。



ユーザーが目的の効果を決定したら、[保存]ボタンをクリックしてset_filter関数を呼び出し、以前に保存した元の画像へのパスと結果の効果を引数として渡します。

最後に、どのように見えるかを示す画面を添付します。

画像







All Articles