Showing posts with label Laravel. Show all posts
Showing posts with label Laravel. Show all posts

Friday, 3 April 2026

Finding Duplicate Photos in Amazon Photos with a Terminal Command

If you use Amazon Photos to back up your pictures, you might have noticed something frustrating over time: duplicate photos. It happens to everyone — you upload a batch of photos twice, you edit a picture and keep both versions, or your phone syncs a photo you already had. Before you know it, your library is cluttered with copies you don't even remember making.                                    

I recently built a command-line tool that connects to your Amazon Photos library and automatically finds those duplicates for you. Let me walk you through how it works.                                  

                                                                                                                                                 The problem with finding duplicates the old way                                                                                                                                                          

The naive approach to finding duplicate files is to compare them byte by byte — if two files are identical down to the last bit, they're duplicates. But photos don't work that well like that. The same picture can exist in your library in slightly different forms: different compression, a small crop, a brightness tweak, or even a different file format (JPEG vs. PNG). Byte-by-byte comparison would miss all of those.                                                                                                                                                                                            

How the tool actually detects duplicates

The tool uses a technique called perceptual hashing. Instead of comparing raw file data, it looks at what the image looks like to the human eye. It converts each photo into a compact "fingerprint" that  captures its visual content, then measures how similar two fingerprints are — giving a percentage from 0% (completely different) to 100% (visually identical).

This means it can detect duplicates even when the files are technically different, as long as the pictures look the same. 

                                                                             

A two-phase process to avoid downloading everything                                                                                                                                                       

Downloading and visually comparing thousands of photos one by one would take forever. The tool is smarter than that: it first does a quick metadata pass to narrow down candidates.

Photos with the same filename, or taken at the exact same second, are very likely to be duplicates. The tool groups those photos together first — without downloading any images. Only then does it download and visually compare the photos within each group. This makes the whole process much faster.


Running the command                                                                                                                                                                                       

The command is photos:find-duplicates. In its simplest form, you just run it and let it scan your entire library:                                                                                         

php artisan photos:find-duplicates                                                                                                                                                                        

You can also narrow things down. For example, to only look at photos uploaded in the last 30 days:                                                                                                        

 php artisan photos:find-duplicates --uploaded-last-days=30                                                                                                                                                

 Or to compare photos taken within a specific date range:

 php artisan photos:find-duplicates --taken-between=01/01/2024,31/12/2024                                                                                                                                  

By default, it groups candidate duplicates by filename. You can also group by the timestamp when the photo was taken, or both at once:                                                                    

php artisan photos:find-duplicates --group-by=taken-at                                                                              php artisan photos:find-duplicates --group-by=name-and-taken-at


The similarity threshold defaults to 90% — photos that look at least 90% alike are flagged as duplicates. You can make it stricter or more lenient:                                                       

php artisan photos:find-duplicates --similarity=95                                                                                                                                                        

Comparing two specific photos                                                                                                                                                                             

Sometimes you already suspect two specific photos are duplicates. Instead of scanning the whole library, you can compare just those two by passing their IDs directly:                                    

php artisan photos:find-duplicates photo-id-1 photo-id-2                                                                                                                                                  

 The tool will tell you the similarity percentage and whether they're considered duplicates. 


More info: https://github.com/icsbcn/awsphotosapi                                                                                                         

Wednesday, 1 April 2026

Never Lose a Photo Again: How I Built a Tool to Organize My Amazon Photos

If you use Amazon Photos to store your pictures, you probably know how easy it is to end up with hundreds — or even thousands — of photos just sitting there, not organized in any album. That was exactly my problem.

I love taking photos. But organizing them? Not so much. Over the years I accumulated a huge collection on Amazon Photos, and most of it was just a big unsorted pile. Albums existed, but plenty of photos never made it into one.

So I built a small tool to help me fix that.

Monday, 22 August 2016

Laravel : Get SQL of a DB object

Hello,

How to print SQL (Select statement) of DB Object in Laravel:

$sql = DB::table('users');
echo $sql->toSql();

Best regards,
Iban Cardona.

Thursday, 28 July 2016

Laravel 4.2 Add get params in URL::action helper function

Hello,

If we want to add get params we need to call function like this:

routes.php

Route::any('test/{id}',  'Controller@index');

blade.php

{{URL::action("Controller@index", array(111, "firstparam" => "aaa"))}}

And result is:
http://www.dummyurl.local/test/111?firstparam=aaa

Best regards,
Iban Cardona.

Thursday, 28 April 2016

Laravel 5.2: Create multilang site (Session+Middleware)

Hello,

How to create a multi-language site in Laravel 5.2:

config/app.php

'locale' => 'ca',
'locales' => ['ca' => 'Català', 'es' => 'Español', 'en' => 'English'],

app/Http/routes.php

Route::group(['middleware' => ['web']], function () {
    Route::get('/', [
        'as' => 'underconstruction', 'uses' => 'Underconstruction\UnderconstructionController@showIndex'
    ]);
    Route::get('/lang/{langcode?}', function ($langcode = 'ca') {
        return redirect()->route('underconstruction');
    });
});


app/Http/Kernel.php

/**
     * The application's route middleware groups.
     *
     * @var array
     */
    protected $middlewareGroups = [
        'web' => [
            \App\Http\Middleware\EncryptCookies::class,
            \Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
            \Illuminate\Session\Middleware\StartSession::class,
            \Illuminate\View\Middleware\ShareErrorsFromSession::class,
            \App\Http\Middleware\VerifyCsrfToken::class,
            \App\Http\Middleware\LangMiddleware::class,
        ],

        'api' => [
            'throttle:60,1',
        ],
    ];


/app/Http/Middleware/LangMiddleware.php

<?php

namespace App\Http\Middleware;

use Closure;
use App;

class LangMiddleware
{
    /**
     * Handle an incoming request.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Closure  $next
     * @return mixed
     */
    public function handle($request, Closure $next)
    {
        $lang = $request->segment(1);
        $locale = $request->segment(2);

        if ($lang == 'lang' && array_key_exists($locale, app()->config->get('app.locales'))) {
            $request->session()->put('locale', $locale);
        } else if ($request->session()->has('locale')) {
            App::setLocale($request->session()->get('locale'));
        }

        return $next($request);
    }
}


/app/Http/Controllers/Underconstruction/UnderconstructionController.php

<?php

namespace App\Http\Controllers\Underconstruction;

use App\Http\Controllers\Controller as Controller;

class UnderconstructionController extends Controller
{
    public function showIndex() {
        return app()->getLocale();
    }
}


If you access to http://yourweb/ --> lang = ca
if you access to http://yourweb/lang/es --> lang = es
If you access to http://yourweb/ --> lang =es

Lang is saved in session data.

Best regards,
Iban Cardona.

Saturday, 10 October 2015

Laravel & TDD: Only test 1 file or function

Hello,

I'm developing with Laravel 5.1 and creating some testing files... http://laravel.com/docs/5.1/testing

I can test all my code executing phpunit inside my project folder but how test only one file/function:

- 1 file: phpunit tests/Auth/UserTest.php
- 1 function: phpunit --filter testRegisterControllerUser tests/Auth/UserTest.php

Best regards,
Iban Cardona.

Friday, 2 October 2015

Using Testing Environment with PHPunit and Laravel

Hello,

Recently I've been using phpunit with Laravel and I found this problem: How to clean or reset my test environment on every test? I did this solution:

Laravel version : 5.1

I followed this tutorial: http://laravel.com/docs/5.1/testing

I created my .env.testing file:

APP_ENV=testing
APP_DEBUG=true
APP_KEY=app_key_testing

DB_CONNECTION=mysql_testing
DB_HOST=localhost
DB_DATABASE=test
DB_USERNAME=dbusernametest
DB_PASSWORD=dbpwdtest

I changed my TestCase.php file:

class TestCase extends Illuminate\Foundation\Testing\TestCase
{
    /**
     * The base URL to use while testing the application.
     *
     * @var string
     */
    protected $baseUrl = 'http://localhost';

    /**
     * Creates the application.
     *
     * @return \Illuminate\Foundation\Application
     */
    public function createApplication()
    {
        $app = require __DIR__.'/../bootstrap/app.php';

        $app->make(Illuminate\Contracts\Console\Kernel::class)->bootstrap();

        return $app;
    }

    public function setUp()
    {
        exec('cp /opt/lampp/htdocs/mytestsite/.env.testing /opt/lampp/htdocs/mytestsite/.env');
        parent::setUp();
        Artisan::call('migrate');
    }

    public function tearDown()
    {
        Artisan::call('migrate:reset');
        parent::tearDown();
        exec('cp /opt/lampp/htdocs/mytestsite/.env.local /opt/lampp/htdocs/mytestsite/.env');
    }
}

I hope you find it useful.

Best regards!

Saturday, 19 September 2015

Install XAMPP + Laravel in Ubuntu

Hello,

Ubuntu version: 14.04.3 LTS
XAMPP version: 5.6.15
Laravel version: 5.2

Install XAMPP (as root)
  • chmod +x xampp-linux-x64-5.6.12-0-installer.run
  • ./xampp-linux-x64-5.6.8-0-installer.run
  • You will be asked to answer some questions, I sayed always Y.
  • To start lampp server: /opt/lampp/lampp start
Install Laravel (as root)
  • Install composer: curl -sS https://getcomposer.org/installer | /opt/lampp/bin/php -- --install-dir=/opt/lampp/bin --filename=composer
  • cd /opt/lampp/htdocs
  • export PATH="$PATH:$HOME/.composer/vendor/bin"
  • export PATH=$PATH:/opt/lampp/bin
  • composer global require "laravel/installer"
  • laravel new test
  • chmod 777 /opt/lampp/htdocs/test/bootstrap/cache
  • chmod -R 777 /opt/lampp/htdocs/test/storage/*
Config Virtual Hosts (as root)
  • vim /opt/lampp/etc/httpd.conf
  • #Include etc/extra/httpd-vhosts.conf --> Include etc/extra/httpd-vhosts.conf
  • Add in /opt/lampp/etc/extra/httpd-vhosts.conf
    •  <VirtualHost *:80>
          ServerAdmin webmaster@dummy-host.example.com
          DocumentRoot "/opt/lampp/htdocs/test/public"
          ServerName testlaravel.com
          ServerAlias www.testlaravel.com
          ErrorLog "logs/testlaravel-error_log"
          CustomLog "logs/testlaravel-access_log" common
      </VirtualHost>
  • /opt/lampp/lampp restart
  • Add in  /etc/hosts
    • 127.0.0.1       testlaravel.com
    • 127.0.0.1       www.testlaravel.com
Done! Go to your browser and write: testlaravel.com...

Tuesday, 2 December 2014

Install MAMP + Laravel 4

Hello,

Today I installed in Mac OS X (10.7.5) server MAMP (3.0.4) + Laravel 4. I did these steps:
  • First, I downloaded and installed MAMP from http://www.mamp.info. I modified default conf changin ports to 80 and 3306.
  • Next, I modified file bash_profile (vim ~/.bash_profile): export PATH=/Applications/MAMP/bin/php/php5.5.10/bin:$PATH alias composer="php /usr/bin/composer.phar" alias laravel="~/.composer/vendor/bin/laravel"
  • Then, I reset terminal and downloaded composer: curl -sS getcomposer.org/installer | php.
  • Next step, move composer.phar: sudo mv composer.phar /usr/bin/
  • I donwloaded Laravel 4 installer: composer global require "laravel/installer=~1.1"
  • I went to /Applications/MAMP/htdocs and I created a new Laravel project: laravel new ibancardonasubiela.tk
  • Then, I created a new virtual host in my MAMP. To do that, I edited file Applications/MAMP/conf/apache/httpd.conf and I uncommented "Include /Applications/MAMP/conf/apache/extra/httpd-vhosts.conf". Then I edited file Applications/MAMP/conf/apache/extra/httpd-vhosts.conf and I added: <VirtualHost *:80>                     DocumentRoot /Applications/MAMP/htdocs/ibancardonasubiela.tk/public                                   ServerName wwww.ibancardonasubiela.local </VirtualHost>
  • I restarted MAMP service.
  • I edited file  /etc/hosts (sudo vim /etc/hosts) adding: 127.0.0.1 www.ibancardonasubiela.local
  • And, finally, Laravel installed in http://www.ibancardonasubiela.local/

Wednesday, 9 July 2014

Laravel 4: Create multi language page with session

Laravel is a strong PHP framework that is widely used. Recently, I was developing with that framework and I needed to create a website with content in 2 languages: catalan and spanish.

To solve this problem you can use some options... like url with language or save language in session. I decided to use the last one.

I created this code:

filters.php

App::before(function($request) {
// We use the locale of the session
if ( Session::has('locale') ) { App::setLocale(Session::get('locale')); }
});

BaseController.php

class BaseController extends Controller {

public function switchLocale($lang) {
// We change the locale lang in the session and redirect back (see filter language in filters.php).
if ( in_array($lang, Config::get('app.available_language')) ) {
Session::put('locale', $lang);
}
return Redirect::back();
}
}

app.php

'locale' => 'es',
'fallback_locale' => 'ca',
'available_language' => array('es', 'ca'),

Finally,  in our view we use this code in the links used to change the language:

Catalan -> URL::action('BaseController@switchLocale', array('ca'))
Spanish -> URL::action('BaseController@switchLocale', array('es'))