
O Campeonato Brasileiro de futebol está se aproximando do fim, ou seja, faltam só 5 rodadas e muita gente quer saber quem será rebaixado(além do Sport, é claro 😃 ) e eu pedi pra o DeepSeek simular os próximos jogos e ele me disse os resultados de todos os jogos e eu preenchi no site do Globo Esporte na opção de Simulação e fiz uma captura de tela de todas as rodadas após recortar todas as seis imagens com resolução iguais: 605x405 pixels.
Então, decidi combinar as imagens em 3 colunas e 2 linhas para que coubesse em uma única imagem para eu postar nas mídias sociais para que todos pudessem ver em uma única imagem todos os resultados e a tabela final em uma única imagem.
E para isso criei um código com C++ e ImageMagick.
Se quiser testar na sua máquina, antes lembre-se de ter instalado o ImageMagick Dev(API .h), para isso rode:
sudo apt install imagemagick graphicsmagick-libmagick-dev-compat1.jpg

2.jpg

3.jpg

4.jpg

5.jpg

6.jpg

Crie um arquivo, por exemplo: brasileirao.cpp e insira esse código:
#include <Magick++.h>
#include <print>
int main(int argc, char** argv){
const std::string filename = "resultado.jpg";
Magick::InitializeMagick(*argv);
const int cols = 3, rows = 2, imgw = 605, imgh = 405, pad = 5;
const Magick::Color bg_color("blue");
std::vector<Magick::Image> imagens;
for(int i = 1; i <= 6; ++i){
std::string nome = std::to_string(i) + ".jpg";
try{
Magick::Image img;
img.read(nome);
img.resize(Magick::Geometry(std::to_string(imgw) + "x" + std::to_string(imgh)));
imagens.push_back(img);
}catch(const std::exception& e){
std::println("{}: {}", nome, e.what());
return EXIT_FAILURE;
}
}
int totalw = cols * imgw + (cols - 1) * pad;
int totalh = rows * imgh + (rows - 1) * pad;
Magick::Image combined(Magick::Geometry(totalw, totalh), bg_color);
combined.matte(true);
size_t index = 0;
for(int r = 0; r < rows; ++r){
for(int c = 0; c < cols; ++c){
if (index >= imagens.size()){
break;
}
int x = c * (imgw + pad);
int y = r * (imgh + pad);
combined.composite(imagens[index], x, y, Magick::OverCompositeOp);
++index;
}
}
combined.write(filename);
std::println("{}: {}x{}", filename, totalw, totalh);
}Se não tiver o C++23, substitua o
std::printlnporstd::cout.
Compile:
g++ $(Magick++-config --cxxflags --cppflags) brasileirao.cpp $(Magick++-config --ldflags --libs)E depois é só rodar o ./a.out que será gerada a imagem: resultado.jpg com as 6 imagens combinadas. Igual a essa abaixo que foi gerada assim:
Clique na imagem para vê-la em alta resolução, ela possui:
1825x815.
Se quiser alterar para usar com suas imagens, altere:
imgw e imgh pela largura e altura das suas imagens, respectivamente;cols e rows de acordo como deseja, note(no código) que no meu caso fiz 2 linhas e 3 colunas;padding(espaço entre as imagens), modificando a variável: pad.
E entre outras coisas que você desejar.Se quiser usar um Makefile:
CC = g++ -std=c++23
DEBUG = -g
OPT = -O1
WARN = -Wall -Werror
INCFLAGS = `Magick++-config --cxxflags --cppflags`
CCFLAGS = $(DEBUG) $(OPT) $(WARN)
LDFLAGS = `Magick++-config --ldflags --libs`
FILES = brasileirao.cpp
all:
$(CC) $(CCFLAGS) $(INCFLAGS) $(FILES) $(LDFLAGS)
@rm -f *.oOu um CMakeLists.txt:
cmake_minimum_required(VERSION 3.16)
project(brasileirao CXX)
# Captura CFLAGS do Magick++
execute_process(
COMMAND Magick++-config --cxxflags --cppflags
OUTPUT_VARIABLE RAW_MAGICKPP_CFLAGS
)
# Captura LDFLAGS do Magick++
execute_process(
COMMAND Magick++-config --ldflags --libs
OUTPUT_VARIABLE RAW_MAGICKPP_LIBS
)
# Limpeza: remove tabs, quebras de linha e espaços excessivos
string(REPLACE "\n" " " MAGICKPP_CFLAGS "${RAW_MAGICKPP_CFLAGS}")
string(REPLACE "\t" " " MAGICKPP_CFLAGS "${MAGICKPP_CFLAGS}")
string(REPLACE "\n" " " MAGICKPP_LIBS "${RAW_MAGICKPP_LIBS}")
string(REPLACE "\t" " " MAGICKPP_LIBS "${MAGICKPP_LIBS}")
string(STRIP "${MAGICKPP_CFLAGS}" MAGICKPP_CFLAGS)
string(STRIP "${MAGICKPP_LIBS}" MAGICKPP_LIBS)
# Agora separa corretamente
separate_arguments(MAGICKPP_CFLAGS)
separate_arguments(MAGICKPP_LIBS)
add_executable(brasileirao brasileirao.cpp)
target_compile_features(brasileirao PRIVATE cxx_std_23)
target_compile_options(brasileirao PRIVATE -g -O1 -Wall -Werror)
target_compile_options(brasileirao PRIVATE ${MAGICKPP_CFLAGS})
target_link_libraries(brasileirao PRIVATE ${MAGICKPP_LIBS})Rode:
cmake -B build . && cmake --build build && ./build/brasileirao
Lembrando que se você usar o Valgring pode obter um falso-positivo, para evitar isso, use a flag: OMP_NUM_THREADS=1, assim:
OMP_NUM_THREADS=1 valgrind --leak-check=full --track-origins=yes ./a.outA saída final será:
ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0).
Só mais uma dica, para usar o ImageMagick no seu LSP inclua no seu ~/.config/clangd/compile_flags.txt a linha:
-I/usr/include/GraphicsMagickOu opcionalmente:
magick++ --cppflags >> .config/clangd/compile_flags.txt
# Ou
pkg-config --cflags Magick++ >> .config/clangd/compile_flags.txt
É uma dica simples, mas que além de ser útil é um bom exercício C++ 😃 .
Fui!