I have 1600 images, each 256px. These images have been sliced in photoshop from an image that is 10240px x 10240px in to the tiles. Problem is, photoshop has named them image_0001.png, image_0002.png...
I would like to rename these in to a usable file name such as image_x_y.png x being tile number in that row, y being tile number in that column...
And ideas how i can automate the renaming of these, or if not how i can pass these images through php, so that i can access image.php?x=2&y=1 ect...
thanks in advance
EDIT:
I have no permission to answer my own question but, used this as renaming would be required on every update. Not ideal...
<?php
$x=$_GET['x'];
$y=$_GET['y'];
$image=(($y-1)*40)+$x;
if ($image<10){
$image="0".$image;
}
$url="tiles/" . $image . ".jpg";
header("Location:" . $url);
?>
You could open the directory containing your files and then create a loop to access all images and rename them, like:
<?php
if ($handle = opendir('/path/to/image/directory')) {
while (false !== ($fileName = readdir($handle))) {
//do the renaming here
//$newName =
rename($fileName, $newName);
}
closedir($handle);
}
?>
Useful functions:
rename(),readdir(), readdir(), str_replace(), preg_replace()
Hope this helps!
You don't have to rename them, just calculate the "linear id" on every access.
so, assuming you have a 40 * 40 set of files, in image.php you'd have something like
$fileid = $x * 40 + y;
$filename = sprintf("image_%04d.png",$fileid);
// send the file with name $filename
What formula you need depends on how it was sliced, could as well be $y * 40 + x
The main advantage is that should your image be updated, it will be ready to use without the intermediate step of renaming the files.
Try this :
$dir = "your_dir";
$i = 0;
$j = 0;
$col = 5;
foreach(glob($dir . '/*') as $file)
{
rename($file, "image"."_".$j."_".$i);
$i++;
if($i % $col == 0)
{
$j++;
}
}
If you know for sure that the routine that converted your files always named the resulting images in the same order
i.e. top left = 0001 ...... Bottom right = 0016
Then it should be fairly simple to write a quick CLI script to go through and rename all your images.
Alternatively if you are going to use that same image converter again many times it may be simpler to make your image.php?x=1&y=2 script workout what file to serve then you wont need to do the renaming every time you get new images.
-read the soure folder with your images (http://php.net/manual/de/function.readdir.php)
-put the part of each imagename between "_" and "."
-parse it ($image_nr) as integer
-do the following:
$y = floor($image_nr/40);
$x = $image_nr%40;
finaly put each image in your destination directory with the new name
I Have not tested it but you could try using this:
$imagesInARow = 10240/256; //=> 40
$rows = 1600 / $imagesInARow; //=> 40
$imageIndex = 1;
for($i = 1; $i <= $rows; $i++) { // row iteration
for($j = 1; $j <= $imagesInARow; $j++) { // columns iteration
rename('image_'. str_pad($imageIndex, 4, '0', STR_PAD_LEFT).'.png',
"image_{$i}_{$j}.png");
$imageIndex ++;
}
}
Related
I am trying to delete items inside List A from list B
And the two inside a text file
Example : a.txt
1
3
6
b.txt
2
3
6
I tried more than one method previously but with large files it does not work as it should
$a = file('a.txt', FILE_IGNORE_NEW_LINES);
$b = file('b.txt', FILE_IGNORE_NEW_LINES);
$n = 'new.txt';
for ($i = 0;$i < count($b);$i++)
{
if (!in_array($b[$i], $a))
{
$c = file_get_contents($n);
$c .= $b[$i] . "\n";
file_put_contents($n, $c);
}
}
Is there a better way to handle large files like 80k line?
This code mainly changes the way the files are read and written, so that the second file is read 1 line at a time and not read all in memory. The output also uses FILE_APPEND in file_put_contents() so that it doesn't need to read the file again.
The first part is to create an array of the a.txt file, with the value as the index to allow you to use isset() rather than in_array() which will make the searching a lot quicker.
Then read the second file 1 line at a time, check if it's present and add the data if needed...
$fileA = fopen('a.txt', 'r');
$a = [];
while($entry = fgets($fileA))
{
$a[trim($entry)] = true;
}
$fileB = fopen('b.txt', 'r');
$n = 'new.txt';
// Clear the file
file_put_contents($n, '');
while($b = fgets($fileB))
{
if (!isset($a[trim($b)]))
{
file_put_contents($n, $b, FILE_APPEND);
}
}
I want to be able to +1 to $i every page reload.
I have come across a very simple issue, that I am struggling to find a solution online.
Heres my code:
$backupNumber = fopen("$v", "r+") or die("Unable to open file!");
$i = fread($backupNumber,filesize("invoices/invoice1/backupN.txt"));
$i = intval($i);
$i = $i + 1;
echo $i;
fwrite($backupNumber,$i);
$a = "invoices/" . $invoiceN . "/backup" . $i;
fclose($backupNumber);
and in the txt file is simply the number '1' to start off with.
The issue occurs when reloading the page when I echo $i it outputs:
2 then 13 then 1214 then 12131215 then 2147483648 etc.
I want it to simple output
2 then 3 then 4 etc
You append the text file, that is why this is happening.
My advice is to use file_get_contents and file_put_contents.
$i = file_get_contents("invoices/invoice1/backupN.txt");
$i++;
Echo $i;
file_put_contents("invoices/invoice1/backupN.txt" $i);
File get and put contents always reads the whole text file.
I don't think you need to intcast the string, it should work without it.
The code can be a one liner too. It's messy but compact.
file_put_contents("invoices/invoice1/backupN.txt", file_get_contents("invoices/invoice1/backupN.txt")+1);
After reading the number from the file, the handle is positioned at its end, so while your math is sound, you're appending the new number to the file instead of overwriting it.
One approach to handle this is to reset the handle use fseek before writing:
fseek($backupNumber, 0);
fwrite($backupNumber, $i);
You are appending the file thats why this is happening. Instead of using r+ mode just use w+ mode.
r+ mode only opens a file and allow you to read and write but dont over write the content.
Where as in w+ mode always a new empty file is created.
Do something like
$backupNumber = fopen("$v", "r+") or die("Unable to open file!");
$i = fread($backupNumber,filesize("invoices/invoice1/backupN.txt"));
fclose($backupNumber);
$backupNumber = fopen("$v", "w+") or die("Unable to open file!");
$i = intval($i);
$i = $i + 1;
echo $i;
fwrite($backupNumber,$i);
$a = "invoices/" . $invoiceN . "/backup" . $i; fclose($backupNumber);
Else you can also you fseek() to point at 0th location in file and override the content in file.
Another variation on a theme perhaps...
function updatecount(){
$file='invoices/invoice1/backupN.txt';
if( !realpath( $file ) )$i=0;
$i=intval( trim( file_get_contents( $file ) ) ) + 1;
file_put_contents( $file, $i );
return $i;
}
$count=updatecount();
echo strval( $count );
Actually I'm using uniqid(); to generate random names:
$file = UPLOAD_DIR . uniqid() . '.png';
The output looks like:
53bd02cdc6b9b.png
53bd02cdc6bd8.png
53bd0320aafbc.png
53bd0320aaff7.png
53bd03e89b8df.png
I want to change these names each file as output:
picture_0001.png
picture_0002.png
picture_0003.png
picture_0004.png
picture_0005.png
Do you have better ideas?
Your want to fix all your current images to the correct format (See # Félix Gagnon-Grenier answer), then once you done that you can do something like the following:
//get array of current images
$imgs = glob(UPLOAD_DIR.'*.png');
//select last image in array, strip out all non-alpha's then pad it with 4 0's
$next = str_pad(preg_replace("/[^0-9]/","", end($imgs))+1, 4, "0", STR_PAD_LEFT);
$file = UPLOAD_DIR.'picture_'.$next.'.png';
Edit
See comments - file based counter
$count_file = UPLOAD_DIR.'count.txt'; //or put somewhere else
//make count file if not exists
if(!file_exists($count_file)){
file_put_contents($count_file,0);
}
//get last image count + 1
$next = file_get_contents($count_file)+1;
//set file var
$file = UPLOAD_DIR.'picture_'.sprintf("%04s",$next).'.png';
//update counter
file_put_contents($count_file, $next);
well, since it hurts your feeling, you seem to be a human being, and I care for human beings. there you go:
I don't know any context, so this may be wildly far from what you actually need.
say your directory is /home/dir
$i = 1;
foreach (scandir('/home/dir') as $file)
{if ($file == '.' || $file == '..') continue;
rename($file,'picture_' . str_pad($i,4,'0',STR_PAD_LEFT) . '.png');
$i++;}
this will generate:
picture_0001.png
picture_0002.png
picture_0003.png
picture_0004.png
picture_0005.png
in place of your old files
I have a file with ~ 10.000 lines inside. I want every time user access my website, it auto pick 10 lines randomly among them.
Code I currently used:
$filelog = 'items.txt';
$random_lines = (file_exists($filelog))? file($filelog) : array();
$random_count = count($random_lines);
$random_file_html = '';
if ($random_count > 10)
{
$random_file_html = '<div><ul>';
for ($i = 0; $i < 10; $i++)
{
$random_number = rand(0, $random_count - 1); // Duplicate are accepted
$random_file_html .= '<li>'.$random_lines[$random_number]."</li>\r\n";
}
$random_file_html .= '</ul>
</div>';
}
When I have < 1000 lines, every things is ok. But now, with 1000 lines. It make my website slow dow significantly.
That I'm thinking to other methods, like:
Divide file to 50 files, select randomly them, then select 10 lines randoms inside the selected file.
-- or --
I knew total lines (items). Make 10 numbers randomly, then read file use
$file = new SplFileObject('items.txt');
$file->seek($ranđom_number);
echo $file->current();
(My server does not support any type of SQL)
Maybe you have other methods that best suit for me. What is best method for my problem? Thank you very much!
The fastest way would be apparently not to pick 10 lines randomly out of a file with ~ 10.000 lines inside on every user's request.
It's impossible to answer more as we know no details of this "XY problem".
If it is possible to adjust the contents of the file then simply pad each of the lines so they have a common length. Then you can access the lines in the file using random access.
$lineLength = 50; // this is the assumed length of each line
$total = filesize($filename);
$numLines = $total/$lineLength;
// get ten random numbers
$fp = fopen($filename, "r");
for ($x = 0; $x < 10; $x++){
fseek($fp, (rand(1, $numLines)-1)*$lineLength, SEEK_SET);
echo fgets($fp, 50);
}
fclose($fp);
try:
$lines = file('YOUR_TXT_FILE.txt');
$rand = array_rand($lines);
echo $lines[$rand];
for 10 of them just put it in a loop:
$lines = file('YOUR_TXT_FILE.txt');
for ($i = 0; $i < 10; $i++) {
$rand = array_rand($lines);
echo $lines[$rand];
}
NOTE: ** the above code does not guarantee that **2 same lines wont be picked. In order to guarantee uniqueness you need to add extra while loop and an array that holds all randomly generated indexes, so next time it generates it and it already exists in an array, generate another one until its not in the array.
The above solution might not be fastest but might fulfill your needs. Since your server does not support any type of SQL, maybe switch to a different server? Because I am wondering how you are storing User Data? Are those stored in files also?
I'm trying to process a for loop within a for loop, and just a little wary of the syntax... Will this work? Essentially, I want to run code for every 1,000 records while the count is equal to or less than the $count... Will the syntax below work, or is there a better way?
for($x = 0; $x <= 700000; $x++) {
for($i = 0; $i <= 1000; $i++) {
//run the code
}
}
The syntax you have will work, but I don't think it's going to do exactly what you want. Right now, it's going to do the outer loop 700,001 times, and for every single one of those 700,001 times, it's going to do the inner loop.
That means, in total, the inner loop is going to run 700,001 x 1001 = about 700.7 million times.
If this isn't what you want, can you give a bit more information? I can't really work out what "I want to run code for every 1,000 records while the count is equal to or less than the $count" means. I don't see any variable named $count at all.
Well, essentially, I'm reading in a text file and inserting each of the lines into a db. I did originally try while(!feof($f)) [where $f = filename], but it keeps complaining of a broken pipe. I thought this would be another way to go
$f should be file-handle returned by fopen(), not a filename.
$file_handle = fopen($filename, 'r');
while(!feof($file_handle)) {
$line = fgets($file_handle);
$line = trim($line); // remove space chars at beginning and end
if(!$line) continue; // we don't need empty lines
mysql_query('INSERT INTO table (column) '
.'VALUES ("'.mysql_real_escape_string($line).'")');
}
Read through the documentation at php.net for fopen(), fgets(). You might also need explode() if you need to split your string.
If your file isn't big, you might want to read it into an array at once like this:
$filelines = file($filename, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
foreach($filelines as $line) {
do_stuff_with($line);
}
Hmm. Ok... Well, essentially, I'm reading in a text file and inserting each of the lines into a db. I did originally try while(!feof($f)) [where $f = filename], but it keeps complaining of a broken pipe. I thought this would be another way to go..
To read a text file line by line I usually:
$file = file("path to file")
foreach($file as $line){
//insert $line into db
}
Strictly answering the question, you'd want something more like this:
// $x would be 0, then 1000, then 2000, then 3000
for($x = 0; $x < 700000; $x += 1000) {
// $i would be $x through $x + 999
for($i = $x; $i < $x + 1000; $i++) {
//run the code
}
}
However, you should really consider one of the other methods for importing files to a database.