Dynamic Image processor
Note: You are free to use the code here, please check the License section for details.
Purpose
Given a Image filename with screensize, bandwidth the program generates an optimal image output on the fly and responds back as content-type:image/jpeg. The image output can be:
a. The output of resized image as Bytes based on bandwidth of network, size requested and screensize
b. The entire image as bytes for a given url passed with content-type as image/jpeg
Primary intent of this program is to embed this and make it imageserver which generates ouput image files dynamically. It provides capability to resize image when WXH is passed in querystring with option to forcefit the size and return or return the best fit option with no aspect ratio loss.
If you dont want to resize but just optimize for a given screensize of rendering with bandwidth in 2g, 3g etc - it optimizes image quality using Pillow-SIMD and returns the output.
Features & Advantages
- Width, height and bandwidth based optimized image outputs.
- Only bandwidth,screensize input can also provide an optimal image which is also configurable.
- Ability to handle 500 and 404. E.g. there is already an inbuilt feature where a default 404image.png is used in case original image is not found. You can put any images like logos, spinner defaults to show in case image is not found.
- WSGIDaemonProcess embedded in Apache means that you can leverage the optimizations from Apache 2.4 here easily including zipping, compression etc.
- You can easily put a frontend nginx or varnish or other proxies which help you to cache them in varnish. There is a imagekey provided uniquely for every width/height or bandwidth/networktype used which you can use as a key, if required and reach out to backend on need basis.
- As this is a very lightweight protocol, you can leverage the webserver to fullscale and offload CPU intensive/IO intensive operations which otherwise would have been the responsibility of your appservers.
DEPENDENCY & SETUP STEPS
Step : 1. The key packages to setup are:
pip install Pillow-SIMD
pip install logging
pip install configparser
pip install setuptools
pip install mod_wsgi
NOTE: Flask provides inherantly, app.logging and configuration files which I havent used and is part of my TODO for next release.
Outside of the above, we have used Flask microframework. It is done to ensure the entire management of base errorhandling, threading of servers are offloaded.
pip install flask
Step : 2. Post above, goto httpd.conf in apache and enable for mod_cgi.so. The best way to find the httpd.conf is to run mod_wsgi-express module-config. Copy all the three lines as given below:
LoadFile "/Users/vph/anaconda/lib/libpython3.6m.dylib"
LoadModule wsgi_module "/Users/vph/anaconda/lib/python3.6/site-packages/mod_wsgi-4.5.16-py3.6-macosx-10.7-x86_64.egg/mod_wsgi/server/mod_wsgi-py36.cpython-36m-darwin.so"
WSGIPythonHome "/Users/vph/anaconda"
Note the order in which the above is to be copied. Copy Loadmodule in httpd.conf in the same section as LoadModule seen. Copy the WSGIPythonHome below or after ServerName section in httpd.conf
Step : 3. Copy the files from this project into a folder e.g. /var/www/imgprocessor. It is important that you execute a command to create default log file in case you dont have root or sudo access. Hence execute the following touch commands to generate default log files where you copied the code files or copy the entire log. This is the reason, I included the log in the repository.
touch imghandler.log
touch dynamicimgprocessor.log
Step : 4. In the code files of imgprocessor.py and imghandler.py - change the log path appropriately. In future release, I will try to get this from configuration. Currently, path used is /var/www/imgprocessor/
Also note the imgprocessor.wsgi which will load the python app running on flask framework.
Step : 5. In case of my mac, I have created the httpd-vhosts.conf as given below for virtualhost configuration. Depending on your OS you may need to create this or other conf file and load it into apache isntance.
<VirtualHost *:80>
ServerAdmin vishnu@gmail.com
ServerName dynamicimgprocessor.com
WSGIDaemonProcess imgprocessor user=vph home=/var/www/imgprocessor threads=40
WSGIScriptAlias /images /var/www/imgprocessor/imgprocessor.wsgi
ErrorLog "/private/var/log/apache2/image_error_log"
CustomLog "/private/var/log/apache2/image_custom_log" common
<Directory "/var/www/imgprocessor">
WSGIProcessGroup dynamicimgprocessor
WSGIScriptReloading On
Options +ExecCGI
Order allow,deny
Allow from all
Require all granted
</Directory>
</VirtualHost>
Important to note a few items above: In case of apache 2.4 - need require all granted, in case of apache 2.2 - need order allow,deny and allow from all section. WSGIScriptReloading is set to on so that any changes to WSGI can happen without restart of apache WSGIScriptAlias as you can see is pointing to /images. Very important to note that it doesnt have a closing backslash which if added would create issues like REDIRECT etc as WSGI script will keep going in loop WSGIDaemonProcess has more options like processes and threads etc. Very important to use this for optimizing your threads and processes for performance.Note also the user with which we are running which is vph in this case.
Step : 6 . This is optional. Outside of the log files of application, we also got the apache common log and errorlog configured as given above which you can change as required.
Step : 7 . Post the above run the command to provide access/ownership to the running process in the /var/www/imgprocessor/. Check that the "vph" user given below is also the same user used in apache WSGIDaemonProcess user. I have given here 755 for the entire folder. Ensure your username for the running process is in sync with the name here.
It is a bad practice to have root user here, so ensure we use a valid user.
cd /var/www/imgprocessor
sudo chown -R vph *.*
sudo chmod 755 *.*
Once the above is done do the following to check all your configurations are correct and run. Depending on your OS, the commands will vary.
sudo apachectl configtest
sudo apachectl restart
The output from first command should be "ok" which means your config is all correct. Once done, restart.
Step : 8 . Then hit the url as given below and review the output.
http://groc-example.com/images/?name=nasa.jpeg&width=340&height=400
You are always welcome to drop me a note if you have questions through Issues section.
Issues Please report issues using the Issues link.
License . You are free to use this but please ensure you provide the due credit to this repository for any fork or download of the code.