├── www.qrpicture.com ├── assets │ ├── index.html │ ├── favicon-152.png │ ├── favicon-192.png │ ├── favicon-32.png │ ├── eVpdGC-186x186.png │ ├── outline0-97x97.png │ ├── outline1-97x97.png │ ├── outline2-97x97.png │ ├── outline3-97x97.png │ ├── outline4-97x97.png │ ├── outline5-97x97.png │ ├── p2G4MC-186x186.png │ ├── qrpicture-420x420.gif │ ├── qrpicture-420x420.jpg │ ├── qrAwesome.anim.col.210x210.gif │ └── qrSpiral.anim.col.210x210.gif ├── images │ └── index.html ├── images.incoming │ └── index.html ├── robots.txt ├── favicon.ico ├── qrcode-mask-93x93.png ├── config.php ├── status.php ├── submit.php ├── index.html ├── qrpicture.css ├── MooTools-More-1.6.0.js └── qrpicture.js ├── assets ├── favicon-32.png ├── favicon-152.png ├── favicon-192.png ├── qrpicture-124x124.png ├── qrpicture-210x210.gif ├── qrpicture-420x420.gif ├── qrpicture-420x420.jpg └── qrpicture-840x420.gif ├── index.md ├── _data └── home.yml ├── CHANGELOG.md ├── _config.yml ├── README.md └── LICENSE.txt /www.qrpicture.com/assets/index.html: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /www.qrpicture.com/images/index.html: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /www.qrpicture.com/images.incoming/index.html: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /www.qrpicture.com/robots.txt: -------------------------------------------------------------------------------- 1 | User-agent: * 2 | Disallow: 3 | -------------------------------------------------------------------------------- /assets/favicon-32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xyzzy/qrpicture/HEAD/assets/favicon-32.png -------------------------------------------------------------------------------- /assets/favicon-152.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xyzzy/qrpicture/HEAD/assets/favicon-152.png -------------------------------------------------------------------------------- /assets/favicon-192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xyzzy/qrpicture/HEAD/assets/favicon-192.png -------------------------------------------------------------------------------- /assets/qrpicture-124x124.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xyzzy/qrpicture/HEAD/assets/qrpicture-124x124.png -------------------------------------------------------------------------------- /assets/qrpicture-210x210.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xyzzy/qrpicture/HEAD/assets/qrpicture-210x210.gif -------------------------------------------------------------------------------- /assets/qrpicture-420x420.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xyzzy/qrpicture/HEAD/assets/qrpicture-420x420.gif -------------------------------------------------------------------------------- /assets/qrpicture-420x420.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xyzzy/qrpicture/HEAD/assets/qrpicture-420x420.jpg -------------------------------------------------------------------------------- /assets/qrpicture-840x420.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xyzzy/qrpicture/HEAD/assets/qrpicture-840x420.gif -------------------------------------------------------------------------------- /www.qrpicture.com/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xyzzy/qrpicture/HEAD/www.qrpicture.com/favicon.ico -------------------------------------------------------------------------------- /www.qrpicture.com/assets/favicon-152.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xyzzy/qrpicture/HEAD/www.qrpicture.com/assets/favicon-152.png -------------------------------------------------------------------------------- /www.qrpicture.com/assets/favicon-192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xyzzy/qrpicture/HEAD/www.qrpicture.com/assets/favicon-192.png -------------------------------------------------------------------------------- /www.qrpicture.com/assets/favicon-32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xyzzy/qrpicture/HEAD/www.qrpicture.com/assets/favicon-32.png -------------------------------------------------------------------------------- /www.qrpicture.com/qrcode-mask-93x93.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xyzzy/qrpicture/HEAD/www.qrpicture.com/qrcode-mask-93x93.png -------------------------------------------------------------------------------- /www.qrpicture.com/assets/eVpdGC-186x186.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xyzzy/qrpicture/HEAD/www.qrpicture.com/assets/eVpdGC-186x186.png -------------------------------------------------------------------------------- /www.qrpicture.com/assets/outline0-97x97.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xyzzy/qrpicture/HEAD/www.qrpicture.com/assets/outline0-97x97.png -------------------------------------------------------------------------------- /www.qrpicture.com/assets/outline1-97x97.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xyzzy/qrpicture/HEAD/www.qrpicture.com/assets/outline1-97x97.png -------------------------------------------------------------------------------- /www.qrpicture.com/assets/outline2-97x97.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xyzzy/qrpicture/HEAD/www.qrpicture.com/assets/outline2-97x97.png -------------------------------------------------------------------------------- /www.qrpicture.com/assets/outline3-97x97.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xyzzy/qrpicture/HEAD/www.qrpicture.com/assets/outline3-97x97.png -------------------------------------------------------------------------------- /www.qrpicture.com/assets/outline4-97x97.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xyzzy/qrpicture/HEAD/www.qrpicture.com/assets/outline4-97x97.png -------------------------------------------------------------------------------- /www.qrpicture.com/assets/outline5-97x97.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xyzzy/qrpicture/HEAD/www.qrpicture.com/assets/outline5-97x97.png -------------------------------------------------------------------------------- /www.qrpicture.com/assets/p2G4MC-186x186.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xyzzy/qrpicture/HEAD/www.qrpicture.com/assets/p2G4MC-186x186.png -------------------------------------------------------------------------------- /www.qrpicture.com/assets/qrpicture-420x420.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xyzzy/qrpicture/HEAD/www.qrpicture.com/assets/qrpicture-420x420.gif -------------------------------------------------------------------------------- /www.qrpicture.com/assets/qrpicture-420x420.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xyzzy/qrpicture/HEAD/www.qrpicture.com/assets/qrpicture-420x420.jpg -------------------------------------------------------------------------------- /www.qrpicture.com/assets/qrAwesome.anim.col.210x210.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xyzzy/qrpicture/HEAD/www.qrpicture.com/assets/qrAwesome.anim.col.210x210.gif -------------------------------------------------------------------------------- /www.qrpicture.com/assets/qrSpiral.anim.col.210x210.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xyzzy/qrpicture/HEAD/www.qrpicture.com/assets/qrSpiral.anim.col.210x210.gif -------------------------------------------------------------------------------- /www.qrpicture.com/config.php: -------------------------------------------------------------------------------- 1 | Click here if you are not redirected. 9 | -------------------------------------------------------------------------------- /_data/home.yml: -------------------------------------------------------------------------------- 1 | navbar_entries: 2 | - title: "showcase" 3 | url: https://xyzzy.github.io 4 | 5 | - title: "qrpicture
" 6 | url: https://github.com/xyzzy/qrpicture 7 | 8 | footer_entries: 9 | - title: "showcase" 10 | url: https://xyzzy.github.io 11 | 12 | - title: "qrpicture
" 13 | url: https://github.com/xyzzy/qrpicture 14 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | All notable changes to this project will be documented in this file. 4 | 5 | The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) 6 | and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html). 7 | 8 | ## [Unreleased] 9 | 10 | ## 2024-01-21 18:28:00 Version 1.5.0 11 | 12 | ``` 13 | 2024-01-21 18:28:00 Removed donate button. 14 | 2024-01-21 18:28:00 Split repository into front-end and back-end (this is the front-end). 15 | ``` 16 | 17 | [Unreleased]: https://github.com/xyzzy/qrpicture/compare/v1.5.0...HEAD 18 | -------------------------------------------------------------------------------- /_config.yml: -------------------------------------------------------------------------------- 1 | title: "qrpicture" 2 | author: "xyzzy@RockingShip.org" 3 | url: https://xyzzy.github.io # root address of the site 4 | description: "Picture to colour QR code converter, hosted on https://QRpicture.com" 5 | favicon: assets/favicon-32.png 6 | favicon152: assets/favicon-152.png 7 | favicon192: assets/favicon-192.png 8 | 9 | # jekyll settings 10 | remote_theme: RockingShip/moonwalk 11 | 12 | # moonwalk 13 | theme_config: 14 | appearance: "dark" # can be "light", "dark" or "auto" 15 | back_home_text: "⍃ home" # customize text for homepage link in post layout 16 | date_format: "%Y-%m-%d" # customize how date is formatted 17 | date_format_post: "%d %B %Y" # customize how date is formatted for blog post headers 18 | show_title: false # show title in home page 19 | show_description: false # show blog description in home page 20 | show_navbar: true # show horizontal navbar in home page 21 | show_footer: true # show footer links in home page,add in _data/home.yml 22 | show_projects: false # show projects as cards, add in _data/home.yml 23 | show_blog: false # show blog add in _posts 24 | show_old_projects: false # show old projects as cards, add in _data/home.yml 25 | show_misc_list: false # show generic vertical list for misc details, add _data/home.yml 26 | 27 | highlighter: rouge 28 | 29 | plugins: 30 | - jekyll-feed 31 | - jekyll-seo-tag 32 | -------------------------------------------------------------------------------- /www.qrpicture.com/status.php: -------------------------------------------------------------------------------- 1 | . 18 | */ 19 | 20 | // attach to session 21 | session_start(); 22 | 23 | // import configuration 24 | require('config.php'); 25 | 26 | // connecting, selecting database 27 | $db = mysqli_init(); 28 | if (!$db) 29 | die(json_encode(array('error' => 'mysqli_init failed'))); 30 | if (!@$db->real_connect($host, $user, $password, $database)) 31 | die(json_encode(array('error' => 'Could not connect: ' . mysqli_connect_error()))); 32 | $query = "set charset utf8"; 33 | $result = $db->query($query); 34 | if (!$result) die(json_encode(array('error' => 'Invalid query: ' . $db->error))); 35 | //--- 36 | 37 | // get posted values 38 | $jobId = @$_REQUEST['jobid']; 39 | 40 | // now, get the number of waiters 41 | $query = 'SELECT id,status,result,imagefilename FROM queue WHERE jobid = "' . $db->real_escape_string($jobId) . '"'; 42 | $result = $db->query($query) or die(json_encode(array('error' => 'Invalid query: ' . $db->error))); 43 | $row = $result->fetch_row(); 44 | if (!$row) 45 | die(json_encode(array('error' => 'Your QR has been removed from the queue'))); 46 | $rowId = $row[0]; 47 | 48 | if ($row[1] == 2) { 49 | $json = json_decode($row[2]); 50 | if (!empty($json->error)) 51 | die(json_encode(array('jobid' => $jobId, 'error' => $json->error, 'imagefilename' => $row[3]))); 52 | if (!empty($json->info)) 53 | die(json_encode(array('jobid' => $jobId, 'info' => $json->info, 'imagefilename' => $row[3]))); 54 | if (!empty($json->elapsed)) 55 | die(json_encode(array('jobid' => $jobId, 'info' => 'Used ' . $json->elapsed . ' CPU seconds. Right-click to save.', 'imagefilename' => $row[3]))); 56 | die(json_encode(array('jobid' => $jobId, 'imagefilename' => $row[3]))); 57 | } 58 | 59 | // now, get the number of waiters 60 | $query = 'SELECT count(*) FROM queue WHERE id<' . $rowId . ' AND status=0'; 61 | $result = $db->query($query) or die(json_encode(array('error' => 'Invalid query: ' . $db->error))); 62 | $row = $result->fetch_row(); 63 | $numWaiters = $row[0]; 64 | 65 | if ($numWaiters == 0) 66 | die(json_encode(array('jobid' => $jobId, 'delay' => 1000, 'info' => 'Your QR is being generated. Please wait.'))); 67 | if ($numWaiters < 5) 68 | die(json_encode(array('jobid' => $jobId, 'delay' => 1000, 'info' => 'Your QR is queued at position #' . $numWaiters))); 69 | die(json_encode(array('jobid' => $jobId, 'delay' => 10000, 'info' => 'Your QR is queued at position #' . $numWaiters))); 70 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: home 3 | title: "qrpicture - Picture to colour QR code converter" 4 | image: assets/qrpicture-420x420.jpg 5 | --- 6 | 7 | \[click on image to jump to the converter\] 8 | [![teaser](assets/qrpicture-420x420.jpg)](https://QRpicture.com) 9 | 10 | # qrpicture 11 | 12 | Create photo and colour QR codes, hosted on [https://QRpicture.com](https://QRpicture.com) 13 | 14 | ### Welcome to the Wonderful World of photo and colour QR's 15 | 16 | Features: 17 | * 93x93 pixel QR code capable of holding 100 characters. 18 | * The size also makes the scanning responsive and fast. 19 | * 186x186 pixel colour information. 20 | * Colours are chosen from a high-contrast QR-safe palette. 21 | * Dithering introduces blurring which reduces sharp contrast edges. 22 | * Repository hosted on [https://QRpicture.com](https://QRpicture.com). 23 | 24 | Creating photo QR's is a two-part process. 25 | 26 | First part (`qrcode`) is to create a 93x93 pixel dithered monochrome image overlaid with mandatory QR pixels. 27 | The applied dithering performs a best match to ensure the CRC is fully compliant. 28 | 29 | The second part (`qrscq`) is to create a 186x186 pixel dithered color image. 30 | The colour palette is created using Spacial Colour Quantification. 31 | 32 | Both parts use the same SCQ dithering mechanism to maximize shades and perception to give the result a natural effect. 33 | 34 | ## Scalable mobile friendly html/css user interface 35 | 36 | The UI design is highly responsive and scales dynamically to screen size and aspect ratio. 37 | The intention is to have a single page interface optimally utilize to the screen using a single layout for both mobile and desktop. 38 | 39 | The only units used are `"%"` which is the percentage of the containing bounding box or `"em"` which is the current font size. 40 | This makes ALL elements/borders/spacing scale to a single base value `"document.body.fontSize"`. 41 | 42 | The general layout if constructed from the screen edges going inward using `"position:absolute"` and `"%"` as units. 43 | Section contents are constructed inwards going outwards using `"position:relative"` and `"em"` as units. 44 | 45 | ## Requirements 46 | 47 | * LAMP environment 48 | * libgd graphical library 49 | * GD-enabled php 50 | * MooTools for DOM/JavaScript connectivity 51 | * The backend found in `qrpicture-backend` repository. 52 | 53 | ## Installation 54 | 55 | See the `qrpicture-backend` repository. 56 | 57 | ## Source code 58 | 59 | Grab one of the tarballs at [https://github.com/xyzzy/qrpicture/releases](https://github.com/xyzzy/qrpicture/releases) or checkout the latest code: 60 | 61 | ```sh 62 | git clone https://github.com/xyzzy/qrpicture.git 63 | ``` 64 | 65 | ## Versioning 66 | 67 | Using [SemVer](http://semver.org/) for versioning. For the versions available, see the [tags on this repository](https://github.com/xyzzy/qrpicture/tags). 68 | 69 | ## License 70 | 71 | This project is licensed under the GNU AFFERO General Public License v3 - see the [LICENSE.txt](LICENSE.txt) file for details 72 | 73 | ## Acknowledgments 74 | 75 | * Masahiro Hara and his work on setting the QR code standard. 76 | * Irving S. Reed and Gustave Solomon for their work on "Reed-Solomon ECC". 77 | * Derrick Coetzee and his amazing work on Spatial Colour Quantization. 78 | * Donald Meagher and his work on octrees for colour quantization. 79 | -------------------------------------------------------------------------------- /www.qrpicture.com/submit.php: -------------------------------------------------------------------------------- 1 | . 18 | */ 19 | 20 | // attach to session 21 | session_start(); 22 | 23 | // import configuration 24 | require('config.php'); 25 | 26 | // connecting, selecting database 27 | $db = mysqli_init(); 28 | if (!$db) 29 | die(json_encode(array('error' => 'mysqli_init failed'))); 30 | if (!@$db->real_connect($host, $user, $password, $database)) 31 | die(json_encode(array('error' => 'Could not connect: ' . mysqli_connect_error()))); 32 | $query = "set charset utf8"; 33 | $result = $db->query($query); 34 | if (!$result) die(json_encode(array('error' => 'Invalid query: ' . $db->error))); 35 | //--- 36 | 37 | // get posted values 38 | $options = array( 39 | 'text' => @$_POST['text'], 40 | 'outlinenr' => @$_POST['outlinenr'], 41 | 'numcolour' => @$_POST['numcolour'], 42 | 'colour' => @$_POST['colour'] 43 | ); 44 | if (isset($_POST['highcontrast'])) { 45 | $s = $_POST['highcontrast']; 46 | if ($s == '1' || $s == 'yes' || $s == 'on' || $s == 'true') 47 | $options['highcontrast'] = 1; 48 | } 49 | if (isset($_POST['colourlow'])) { 50 | $s = $_POST['colourlow']; 51 | if ($s == '1' || $s == 'yes' || $s == 'on' || $s == 'true') 52 | $options['colourlow'] = 1; 53 | } 54 | $imageB64 = @$_POST['image']; 55 | if (empty($imageB64)) 56 | die(json_encode(array('error' => 'Missing image'))); 57 | 58 | // lock the table 59 | $query = "LOCK TABLES queue LOW_PRIORITY WRITE"; 60 | $result = $db->query($query) or die(json_encode(array('error' => 'Invalid query: ' . $db->error))); 61 | // create job ID 62 | $jobId = ''; 63 | for ($retry = 0; $retry < 10; $retry++) { 64 | 65 | // create idstring 66 | $keyString = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; 67 | $v = rand(); 68 | for ($i = 0; $i < 6; $i++) { 69 | $jobId .= $keyString[$v % 62]; 70 | $v /= 62; 71 | } 72 | 73 | $query = 'SELECT count(*) FROM queue WHERE jobid="' . $db->real_escape_string($jobId) . '"'; 74 | $result = $db->query($query) or die(json_encode(array('error' => 'Invalid query: ' . $db->error))); 75 | $row = $result->fetch_row(); 76 | if (!$row[0]) 77 | break; // free to use 78 | 79 | $jobId = ''; 80 | } 81 | if (!$jobId) 82 | die(json_encode(array('error' => 'Failed to create Job ID'))); 83 | 84 | $query = 'INSERT INTO queue (jobid, options, txt, outlinenr, numcolour, imageb64) VALUES (' . 85 | '"' . $db->real_escape_string($jobId) . '",' . 86 | '"' . $db->real_escape_string(json_encode($options)) . '",' . 87 | '"' . $db->real_escape_string($options['text']) . '",' . 88 | '"' . $db->real_escape_string($options['outlinenr']) . '",' . 89 | '"' . $db->real_escape_string($options['numcolour']) . '",' . 90 | '"' . $db->real_escape_string($imageB64) . '")'; 91 | 92 | $result = $db->query($query) or die(json_encode(array('error' => 'Invalid query: ' . $db->error))); 93 | $rowId = $db->insert_id; 94 | 95 | // unlock tables 96 | $query = "UNLOCK TABLES"; 97 | $result = $db->query($query) or die(json_encode(array('error' => 'Invalid query: ' . $db->error))); 98 | 99 | // now, get the number of waiters 100 | $query = 'SELECT count(*) FROM queue WHERE id<' . $rowId . ' AND status=0'; 101 | $result = $db->query($query) or die(json_encode(array('error' => 'Invalid query: ' . $db->error))); 102 | $row = $result->fetch_row(); 103 | $numWaiters = $row[0]; 104 | 105 | if ($numWaiters == 0) 106 | die(json_encode(array('jobid' => $jobId, 'delay' => 1000, 'info' => 'Your QR is being generated. Please wait.'))); 107 | if ($numWaiters < 5) 108 | die(json_encode(array('jobid' => $jobId, 'delay' => 1000, 'info' => 'Your QR is queued at position #' . $numWaiters))); 109 | die(json_encode(array('jobid' => $jobId, 'delay' => 10000, 'info' => 'Your QR is queued at position #' . $numWaiters))); 110 | -------------------------------------------------------------------------------- /www.qrpicture.com/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 22 | 23 | Picture to colour QR code converter 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 |
49 | 59 |
60 |
61 |
62 |
63 |
    64 |
  • 1: Image
  • 65 |
  • 2: Outline
  • 66 |
  • 3: Clip
  • 67 |
  • 4: Text
  • 68 |
  • 5: Create
  • 69 |
70 |
71 |
72 |
73 |
74 |
75 |

Select your image

76 |
    77 |
  • will be resized to 93x93 pixels
  • 78 |
  • will be blurred and dithered just as the preview
  • 79 |
  • you can clip/size the preview
  • 80 |
  • supported formats JPG/PNG/GIF
  • 81 |
  • animations not supported (yet)
  • 82 |
83 | 84 |
85 |
86 |

Select outline

87 |

88 | round 89 | corners 90 | horizontal 91 | vertical 92 |

93 |
94 |
95 |

Position and size clip rectangle

96 |
97 |
98 | 99 |
100 | 101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 | 114 |
115 |
116 |
117 |

Your text/message

118 |
    119 |
  • maximum 100 characters
  • 120 |
  • text can also be a valid web address
  • 121 |
  • shorter text gives better dither quality
  • 122 |
  • you need to add text or your QR might not scan
  • 123 |
124 |
125 | 126 |
127 |
128 | 129 |
130 |
131 |
132 |

Choose what to create:

133 | 134 |
    135 |
  • please be patient, generator has a queue
  • 136 |
  • right-click/long-press to save
  • 137 |
  • the white border size is specification mandatory
  • 138 |
139 | 140 |
141 | 145 |
146 |
147 | 151 |
152 | 153 |
154 | 155 |
156 | 157 |
158 |
159 |
160 |
161 |
162 |
163 |
164 |
165 |
166 |
167 |
example
168 |
example
169 |
170 |
171 |

Sources of this site can be found https://github.com/xyzzy/qrpicture.

172 |

This service is available in the hope that it will be useful, but without any warranty; 173 | without even the implied warranty of merchantability or fitness for a particular purpose.

174 |

Instead of an ad with tracking… Want to donate opencollective some appreciation for the use or inspiration this gives you?

175 |
176 |
177 |
178 |
179 | 180 | 181 | -------------------------------------------------------------------------------- /www.qrpicture.com/qrpicture.css: -------------------------------------------------------------------------------- 1 | @charset "utf-8"; 2 | 3 | /* 4 | * This file is part of qrpicture, picture to colour QR code converter. 5 | * Copyright (C) 2007, xyzzy@rockingship.org 6 | * 7 | * This program is free software: you can redistribute it and/or modify 8 | * it under the terms of the GNU Affero General Public License as published 9 | * by the Free Software Foundation, either version 3 of the License, or 10 | * (at your option) any later version. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU Affero General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU Affero General Public License 18 | * along with this program. If not, see . 19 | */ 20 | 21 | /* 22 | * Top-level is a wrapped 5x5 grid. 23 | * - 4 corners with logos 24 | * - 3x1 head+tail 25 | * - 3x3 main 26 | * - 1x3 left/right 27 | * 28 | * Area's are 'position:absolute' and exclusively using '%' as unit to create them 'outside-to-inside'. 29 | * 30 | * NOTE: all names starting with 'qr' are accessed from javascript 31 | */ 32 | 33 | /* 34 | * explicit defaults 35 | */ 36 | 37 | div { position: relative; } 38 | img { margin: 0; padding: 0; border: none; } 39 | input { font-size: 1em; } 40 | p { margin: 0.5em 0; } 41 | span.small { font-size: 0.8em; } 42 | span.large { font-size: 1.125em; } 43 | span.xlarge { font-size: 1.5em; } 44 | span.xxlarge { font-size: 2em; } 45 | 46 | a > img { 47 | display: inline; 48 | vertical-align: middle; 49 | } 50 | 51 | /* 52 | * top-level Layout 53 | */ 54 | body { 55 | position: absolute; 56 | width: 100%; 57 | height: 100%; 58 | top: 0; 59 | right: 0; 60 | bottom: 0; 61 | left: 0; 62 | margin: 0; 63 | padding: 0; 64 | font-family: Verdana, Geneva, sans-serif; 65 | font-size: 10pt; 66 | font-weight: normal; 67 | border: none; 68 | overflow: hidden; /* firefox will otherwise display scrollbars when extremely narrow */ 69 | background-color: #ccc; 70 | } 71 | 72 | div#wrapper { 73 | position: absolute; 74 | width: 96%; 75 | height: 96%; 76 | top: 2%; 77 | right: 2%; 78 | bottom: 2%; 79 | left: 2%; 80 | margin: 0; 81 | padding: 0; 82 | } 83 | 84 | div#head { 85 | position: absolute; 86 | width: 100%; 87 | height: 20%; 88 | top: 0; 89 | left: 0; 90 | } 91 | 92 | div#tail { 93 | position: absolute; 94 | width: 100%; 95 | height: 20%; 96 | left: 0; 97 | bottom: 0; 98 | } 99 | 100 | div.headtail-left { 101 | position: absolute; 102 | width: 20%; 103 | height: 100%; 104 | top: 0; 105 | left: 0; 106 | } 107 | 108 | div.headtail-middle { 109 | position: absolute; 110 | width: 60%; 111 | height: 100%; 112 | top: 0; 113 | left: 20%; 114 | overflow: hidden; 115 | } 116 | 117 | div.headtail-right { 118 | position: absolute; 119 | width: 20%; 120 | height: 100%; 121 | top: 0; 122 | right: 0; 123 | } 124 | 125 | div#main { 126 | position: absolute; 127 | width: 100%; 128 | height: 60%; 129 | top: 20%; 130 | right: 0; 131 | bottom: 20%; 132 | left: 0; 133 | } 134 | 135 | /* 136 | * All content divs are mostly "position:relative" to create them inside-to-outside and allow shrinkwrapping of contents. 137 | * 138 | * All units are either in '%' of containing folder or 'em' (the current font size) 139 | * 140 | * The main scale is relative to the corner QR's which (for the site) can contain 8 lines of text. 141 | * To minimize rounding errors, line-height is set to 10/8 = 1.25 of font size. 142 | * This makes the QR logo 10em wide/high. 143 | * 144 | * Font-size and line-height are set on resize events to scale to the page dimension depending on portrait/landscape mode. 145 | * note: DO NOT USE small/large/xlarge/xxlarge directly as they do not change on client resize. 146 | */ 147 | 148 | div.headtail img.example { 149 | position: absolute; 150 | width: 10em; 151 | height: 10em; 152 | top: 0; 153 | right: 0; 154 | bottom: 0; 155 | left: 0; 156 | margin: auto; /* center */ 157 | } 158 | 159 | div.headtail-middle div { 160 | /* center div */ 161 | position: absolute; 162 | width: 94%; 163 | top: 50%; 164 | right: 3%; 165 | left: 3%; 166 | margin: auto; /* center */ 167 | -webkit-transform: translateY(-50%); 168 | -ms-transform: translateY(-50%); 169 | transform: translateY(-50%); 170 | } 171 | 172 | div.main-middle { 173 | position: absolute; 174 | width: 100%; 175 | height: 100%; 176 | top: 0; 177 | right: 0; 178 | bottom: 0; 179 | left: 0; 180 | margin: 0; 181 | padding: 0; 182 | } 183 | 184 | div.head p, div.tail p { 185 | margin: 0.8em 0; /* controlled line-separator margin around

*/ 186 | } 187 | 188 | p.head1 { 189 | font-size: 2em; 190 | text-align: center; 191 | font-weight: bold; 192 | } 193 | 194 | p.head2 { 195 | font-size: 1.125em; 196 | text-align: center; 197 | font-style: italic; 198 | } 199 | 200 | p.tail1 { 201 | font-size: 1em; 202 | text-align: center; 203 | } 204 | 205 | p.tail1 a { 206 | text-decoration: none; 207 | white-space: nowrap; 208 | } 209 | 210 | p.tail2 { 211 | font-size: 0.6em; 212 | text-align: center; 213 | font-style: italic; 214 | } 215 | 216 | /* 217 | * center/main area 218 | */ 219 | 220 | form { 221 | font-size: calc(1em * 30 / (30 + 1.25 + 2 * (.3 + .6))); /* = width/height. NOTE: this changed em. shrink so that height fits in 30em */ 222 | position: absolute; 223 | width: 30em; 224 | height: calc(30em + 1.25em + 2 * (.3em + .6em)); /* tabPane.height + mainPane.height */ 225 | top: 0; 226 | right: 0; 227 | bottom: 0; 228 | left: 0; 229 | margin: auto; /* center */ 230 | padding: 0; 231 | } 232 | 233 | .tabPane { 234 | font-size: 0.88em; /* NOTE: this changed em. let all buttons fit on same line */ 235 | position: relative; 236 | height: calc(1.25em + 2 * .3em + 2 * .6em); /* line-height + 2x li.padding + 2x li.margin */ 237 | margin: auto; /* center */ 238 | padding: 0; 239 | text-align: center; 240 | } 241 | 242 | .mainPane { 243 | font-size: calc(1em * 30 / (30 + 2 * (.5 + .2))); /* NOTE: this changed em. scale inner width/height to match 30em*30em */ 244 | position: absolute; 245 | width: 30em; 246 | height: 30em; 247 | right: 0; 248 | bottom: 0; 249 | left: auto; 250 | margin: auto; /* center */ 251 | padding: .5em; 252 | border: .2em solid gray; 253 | } 254 | 255 | /* 256 | * Contents Pane layout 257 | */ 258 | 259 | /* slider viewport */ 260 | .contentViewport { 261 | position: relative; 262 | width: 100%; 263 | height: 100%; 264 | border: none; 265 | margin: 0; 266 | overflow: hidden; 267 | } 268 | 269 | /* slider full-contents */ 270 | .qrContentSlider { 271 | position: relative; 272 | width: 1000%; 273 | height: 100%; 274 | margin: 0; 275 | padding: 0; 276 | border: none; 277 | } 278 | 279 | /* slider tab pane */ 280 | .contentPane { 281 | position: relative; 282 | float: left; 283 | width: 10%; 284 | height: 100%; 285 | margin: 0; 286 | } 287 | 288 | /* 289 | * button. Height = 3.05em = 1.25 (line height) + 2*(.6+.3) (border+padding) 290 | */ 291 | .button { 292 | margin: .6em .3em; 293 | padding: .3em .6em; 294 | background: #888; 295 | color: #000; 296 | border-radius: 1em; 297 | border: none; 298 | -webkit-user-select: none; 299 | -ms-user-select: none; 300 | user-select: none; 301 | } 302 | 303 | .button:hover, .button:disabled { 304 | background: #aaa; 305 | } 306 | 307 | /* 308 | * steps/progress