I've been following this tutorial, and I've got to the point where we are instructed how to load and use bitmaps. Here is the current code:
#include "SDL/SDL.h"
#include <stdlib.h>
int main (int arg, char *argc[]) {
SDL_Surface* screen = NULL;
SDL_Surface* hello = NULL;
SDL_Init(SDL_INIT_EVERYTHING);
screen = SDL_SetVideoMode (256, 256, 32, SDL_SWSURFACE);
hello = SDL_LoadBMP("hello world.png"); // Here
if (hello == NULL) exit(0);
SDL_BlitSurface(hello, NULL, screen, NULL);
SDL_Flip(screen);
SDL_Delay(2000);
SDL_FreeSurface(hello);
SDL_Quit();
return 0;
}
hello, however, never gets any value other than NULL. I'm using Code::Blocks, and even if I scatter hello world.png through all possible directories of the project (be it inside bin, obj, either of the Debug's, the directory with the .cbp) or specify the whole path to the image in-code (as in SDL_LoadBMP("C:\Dir\hello world.png")) hello will get NULL.
What am I doing wrong?
OS is Windows
EDIT: Alright, apparently SDL_LoadBMP can only load .bmp files! How silly of me.
Edit: I mixed SDL_LoadBMP with IMG_Load, here's my new answer:
You can use SDL Image (include SDL_Image.h, link SDL_image.lib and make sure that the correct DLL for you file type is with your binary, if you need one) to call IMG_Load. IMG_Load will take care to resolve your file type and use the appropriate loaded to create a new SDL Surface. Remember to Free your surface when you're done with it.
Yes, it only loads bitmaps. You can use SDL_Image to load other types such as a png.
Related
I've created a repository that has the most basic way to reproduce my issue. I use Cmake to build and it's set up to statically link freetype into my executable.
FreeType is a submodule, so you can clone it all at once with:
git clone --recurse-submodules https://github.com/jeffw387/freetype_minimum_test
or if you prefer just clone freetype from git into the externals directory.
I'm currently testing on Ubuntu.
I can initialize FreeType, create a face from the font, and load a glyph from a character code with the FT_LOAD_RENDER flag all without errors.
Then when I inspect the bitmap buffer, it's zero-initialized on every row. I used gdb from within VS Code in order to inspect the buffer, but before that I also tried copying out the data line by line.
The font I'm testing with is a free font I found online, but I was able to test it in Libre Office and it seems to work just fine.
Can anyone spot a problem with the code? If anyone is willing I'd love to know if this repo creates the same issue on their machine.
Here's my cpp file for easy viewing:
#include <ft2build.h>
#include FT_FREETYPE_H
#include <iostream>
#include <vector>
int main() {
FT_Library library{};
if (FT_Init_FreeType(&library)) {
std::cout << "Error initializing FreeType.";
}
FT_Face face{};
auto faceResult = FT_New_Face(library, "Anke.ttf", 0, &face);
if (faceResult) {
std::cout << "Error creating face.";
}
if ((face->face_flags & FT_FACE_FLAG_SCALABLE) != FT_FACE_FLAG_SCALABLE) {
std::cout << "Error: font is not scalable.";
}
if (FT_Set_Pixel_Sizes(face, 0, 50)) {
std::cout << "Error setting font pixel size.";
}
if (FT_Load_Char(face, 'P', FT_LOAD_RENDER)) {
std::cout << "Error loading or rendering glyph.";
}
auto bmp = face->glyph->bitmap;
return 0;
}
I've done some further testing and it seems like there was a problem with my freetype fork. I haven't gone to the trouble of figuring out what it was, but in any case now that I've tried it with a fresh clone from https://github.com/aseprite/freetype2 it works.
When I use this code to load an image for SDL to render:
SDL_Texture* testimg = IMG_LoadTexture(renderer, "testz.bmp");
(or)
SDL_Texture* testimg = IMG_LoadTexture(renderer, "/testz.bmp");
the image doesn't render at all. However... if I use this code:
SDL_Texture* testimg = IMG_LoadTexture(renderer, "../bin/testz.bmp");
SDL draws the image just fine. "bin" is the folder the .exe is in. So how do I fix this file paths issue?
edit: another possibility may be that visual studio, for some reason, is running the exe it put in the bin folder in another location which doesnt have the image...
Because the directory where your executable is installed is not the same thing as the current directory of the process that your operating system starts, when it runs this executable.
It's fairly obvious that the current directory of your started process is the sibling directory of its executable.
One thing that might work is to use argv[0] to make sure the correct base path is used. Assuming you're using standard main(), it would go something like this:
std::string base_path;
int main(int argc, char* argv[]) {
base_path = argv[0];
size_t last_slash = base_path.find_last_of('/');
if(last_slash == std::string::npos)
base_path = ".";
else base_path.erase(last_slash + 1);
// Anything else you need to do in `main()`
return 0;
}
And then your loading would look like this:
SDL_Texture* testimg = IMG_LoadTexture(renderer, base_path + "testz.bmp");
If it's in a different file than main(), you'll also need to redeclare base_path with extern:
extern std::string base_path;
And of course you need to #include <string> for this to work.
If all your loading is done in main(), you can make this a bit better by moving the declaration of base_path into main():
int main(int argc, char* argv[]) {
std::string base_path = argv[0];
// The rest is the same
}
I am trying to load a bitmap with allegro 5.0.10
ALLEGRO_PATH *path = al_get_standard_path(ALLEGRO_RESOURCES_PATH);
al_set_path_filename(path, "Bitmap.bmp");
al_init_image_addon();
ALLEGRO_BITMAP *bmp = al_load_bitmap(al_path_cstr(path, '/'));
if (!bmp) {
fprintf(stderr, "No Background.bmp in this directory...");
return -2;
}
al_draw_bitmap(bmp, 0, 0, 0);
Once i tried to run the program in debug mode, i get this error:
Assertion failed!
Program: c:\allegro\bin\allegro-5.0.10-monolith-md-debug.dll
File: allegro-git\src\system.c
Line: 336
Expression: active_sysdrv
...
How do i fix this?
You need to initialize allegro by calling al_init(). Very few Allegro functions can be called before doing that.
#junyi00, you need to make sure that you call al_init() before trying to load any resources. In your code above, make sure al_init() is already called before calling al_get_standard_path(ALLEGRO_RESOURCES_PATH), al_set_path_filename(path, "Bitmap.bmp"), al_load_bitmap(al_path_cstr(path, '/')) and basically all the Allegro functions from there. No other Allegro functions can be called before this function except one or two. See http://manpages.ubuntu.com/manpages/artful/en/man3/al_init.3alleg5.html and http://manpages.ubuntu.com/manpages/zesty/en/man3/al_install_system.3alleg5.html These are links to the al_init() and al_install_system() Allegro function manual pages
Original question:
I've been asked prior to a job interview to understand how an
anti-aliased line is drawn in a framebuffer, using C or C++. I haven't
used C, and it's been a few years for me since last using C++. I am a
complete beginner when it comes to graphics. My C++ experience has
mostly been in simple command-line programs and sorting methods. The
company does not care if I grab the code online, they want me to
understand it but still have a working executable.
I've used this tutorial to set up SDL libraries in MS VC++ 2012
Express, and this algorithm for the actual anti-aliasing. I have
a good understanding of the algorithm, though I'm currently having
trouble getting it to compile. I just want a line to be drawn, and
then I can go forward with setting the code up to the skeleton class
definitions I was given. This is what I have included aside from what
is on that page with the algorithm:
#include <cmath>
#include <math.h>
#include "conio.h"
#include "stdlib.h"
#include "stdio.h"
#include "SDL.h"
const double HEIGHT = 240;
const double WIDTH = 320;
const double X0 = 25.6;
const double X1 = 64.7;
const double Y0 = 30;
const double Y1 = 42;
int round(double number)
{
return number < 0.0 ? ceil(number - 0.5) : floor(number + 0.5);
}
void main()
{
Uint32 pixelColor = 00000000000000000000000000000000;
SDL_Surface* myScreen = SDL_CreateRGBSurface(SDL_ALPHA_OPAQUE,WIDTH,HEIGHT,32, 0x000000FF,
0x0000FF00, 0x00FF0000, 0xFF000000);
WULinesAlpha(X0, X1, Y0, Y1,pixelColor,myScreen);
return;
}
I'm getting the following errors:
Error 21 error LNK2019: unresolved external symbol _SDL_main
referenced in function _main Error 22 error LNK1120: 1 unresolved
externals
I've seen a few code examples saying the main function has to look
like this:
int main(int argc, char *argv[])
{
}
Again, graphics stuff is unfamiliar to me so I know my main function
is likely very wrong; I'm anticipating some shaking heads. Can someone
explain what is happening/what I need to do?
New:
I have now replaced my main function with the following code, based on NomNomNom069's YouTube video: "C++ SDL Tutorial 2 Creating a Screen and Handling Basic Input"
#include "SDL.h"
int main(int argc, char * args[])
{
bool running = true;
//initialize SDL
if (SDL_Init(SDL_INIT_EVERYTHING) == -1)
{
running = false;
}
//set up screen
SDL_Surface *screen;
screen = SDL_SetVideoMode(WIDTH, HEIGHT, 32, SDL_HWSURFACE);
if (screen == NULL)
{
running = false;
}
SDL_Event occur;
//main application loop
while (running)
{
SDL_PollEvent(&occur);
if (occur.type == SDL_QUIT)
{
running = false;
}
//drawing occurs here
SDL_FillRect(screen, NULL, 0);
SDL_Flip(screen);
}
//quit SDL
SDL_Quit();
return 0;
}
No errors, and I get a window to pop up. Awesome.
My question now is regarding how/where to call WuLinesAlpha. This function calls for 4 doubles, a Uint32 variable, and an SDL_Surface*. I have my doubles, I set the Uint32 to 0x000000FF, and I assume that the SDL_Surface I have set up as screen is the one passed in.
I've toyed around with where the WuLinesAlpha function call goes and I keep getting the black screen. I thought, as explained in the video, it would go in the loop but nothing has happened. Are there any more SDL commands I should be calling?
Fix your main declaration first. This does need to be int main(int argc, char *argv[]). Especially on Windows, since I believe SDL.h actually renames your main to some other name, and takes over main for the library itself.
Next, make sure you link against SDL properly. In my own SDL 1.2.x based project I have these lines in my Makefile:
SDL_CFLAGS := $(shell sdl-config --cflags)
SDL_LFLAGS := $(shell sdl-config --libs)
I then later append those flags to my actual CFLAGS and LFLAGS. Note that if you use make and Makefiles, you want to use := there, otherwise make will invoke the $(shell ...) command every time it expands $(CFLAGS).
I can't help you set up Microsoft's GUI products. This tutorial, for a slightly older MSVC product (2010), looks pretty good, and may put you on the right track: http://lazyfoo.net/SDL_tutorials/lesson01/windows/msvsnet2010e/index.php
And finally, don't forget to call SDL_Init() at some point, preferably before you start creating surfaces.
Good luck!
I am trying to do console application to read pixels from image:
#include <QtCore/QCoreApplication>
#include <QtGui/QImage>
#include <iostream>
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
QImage *img = new QImage("adadad.jpg");
//std::cout << "Type filename:" << std::endl;
img->isNull();
return a.exec();
}
That doesn't work I got: (IT doesn't compile, but anyway file isn't exist yet...)
File not found: tmp/obj/debug_shared/main.o:: In function `main':
What is going on? Is it impossible to use Qimage with console app?!
EDIT:
screen
It is possible to use QImage in a console application, you must make sure that QtGui is configured though. If you chose a console app, your .pro file might contain something like
CONFIG += console
QT -= gui
If that's the case, remove the QT -= gui line.
QImage("adadad.jpg");
Will probably look for a file called adadad.jpg on the current working directory for your application. Check if that file is present. Otherwise, use a fully qualified path.
img->isNull() doesn't do anything on it's own, try this instead:
if(img->isNull())
std::cout << "Image isNull!\n";
else
std::cout << "Image loaded\n";
My guess is that the local directory of the executable is not the same as the location of that image, so Qt can't find the file. Try specifying the complete path.
EDIT: Ahh... didn't realize it was a compilation problem. That looks suspiciously like a moc issue. What build system are you using? and can you confirm that the moc step is executing?
This modification of your code will compile and run as expected if there is a valid image file in the current working directory when you run the app. It will display Image loaded
#include <QtGui/QImage>
#include <iostream>
int main(int argc, char *argv[])
{
QImage *img = new QImage("adadad.jpg");
if(img->isNull())
std::cout << "Image is null";
else
std::cout << "Image loaded";
return 0;
}
You do not need to create an instance of QCoreApplication unless you have subclassed it and put your program code in that subclass.
Update:
Your program does not exit so you are probably getting that compile error because it can't replace the executable because it is still running (and locked). The file locking is more likely to be an issue under Windows.
An important note when you are loading a file using directly "adadad.jpg" in your code. Even if you put the file inside the debug/release folder, QImage will always be null if loaded this way.
I run into this problem yesterday and I fixed it by using the Qt library to get the full path: QCoreApplication::applicationDirPath().
There is two way to achieve that, first one is when you create the img object.
QImage img( QCoreApplication::applicationDirPath() + "adadad.jpg");
if( img.isNull())
{
qDebug() << "Loading Error - file: adadad.jpg.";
return false;
}
or using the load function
QImage img;
if( !img.load(QCoreApplication::applicationDirPath() + "adadad.jpg"))
{
qDebug() << "Loading Error - file: adadad.jpg.";
return false;
}