def serve_qr_code_image(request): """Serve an image that represents the requested QR code.""" qr_code_options = get_qr_code_option_from_request(request) # Handle image access protection (we do not allow external requests for anyone). check_image_access_permission(request, qr_code_options) text = base64.urlsafe_b64decode(request.GET.get('text', '')) img = make_qr_code_image( text, image_factory=SvgPathImage if qr_code_options.image_format == SVG_FORMAT_NAME else PilImageOrFallback, qr_code_options=qr_code_options) # Warning: The largest QR codes, in version 40, with a border of 4 modules, and rendered in SVG format, are ~800 # KB large. This can be handled in memory but could cause troubles if the server needs to generate thousands of # those QR codes within a short interval! Note that this would also be a problem for the CPU. Such QR codes needs # 0.7 second to be generated on a powerful machine (2017), and probably more than one second on a cheap hosting. stream = BytesIO() if qr_code_options.image_format == SVG_FORMAT_NAME: img.save(stream, kind=SVG_FORMAT_NAME.upper()) mime_type = 'image/svg+xml' else: img.save(stream, format=PNG_FORMAT_NAME.upper()) mime_type = 'image/png' # Go to the beginning of the stream. stream.seek(0) # Build the response. response = HttpResponse(content=stream, content_type=mime_type) return response
def make_embedded_qr_code(text, qr_code_options=QRCodeOptions()): """ Generates a <svg> or <img> tag representing the QR code for the given text. This tag can be embedded into an HTML document. """ image_format = qr_code_options.image_format img = make_qr_code_image(text, SvgEmbeddedInHtmlImage if image_format == SVG_FORMAT_NAME else PilImageOrFallback, qr_code_options=qr_code_options) stream = BytesIO() if image_format == SVG_FORMAT_NAME: img.save(stream, kind=SVG_FORMAT_NAME.upper()) html_fragment = (str(stream.getvalue(), 'utf-8')) else: img.save(stream, format=PNG_FORMAT_NAME.upper()) html_fragment = '<img src="data:image/png;base64, %s" alt="%s">' % (str(base64.b64encode(stream.getvalue()), encoding='ascii'), escape(text)) return mark_safe(html_fragment)