I need your help! Im currently really new to wxWidgets as a uni student. I am trying to load a .gif file using wxWidgets. I tried using the code below... but it only loads 1 frame, it doesn't move/ change to the other frames, it's basically a still picture. The file is .gif extension, and it has 3 frames or so. The location of the image is already correct. Help would be much appreciated!
Thank you
#include "ImageWindow.h"
#include <wx/stdpaths.h>
#include <wx/filename.h>
BEGIN_EVENT_TABLE(ImageWindow, wxWindow)
EVT_PAINT(ImageWindow::OnPaint)
END_EVENT_TABLE()
ImageWindow::ImageWindow(wxFrame *parent)
: wxWindow(parent, wxID_ANY)
{
this->SetBackgroundColour(wxColour(*wxWHITE));
wxImageHandler *gifLoader = new wxGIFHandler();
wxImage::AddHandler(gifLoader);
this->LoadPotatoBitmap();
}
ImageWindow::~ImageWindow()
{
delete potatoBitmap;
}
void ImageWindow::LoadPotatoBitmap()
{
wxStandardPaths &stdPaths = wxStandardPaths::Get();
wxString fileLocation = stdPaths.GetExecutablePath();
wxImage image(wxT("A:\\Projects\\TestGif\\Assets\\Kuning.gif"),
wxBITMAP_TYPE_GIF);
potatoBitmap = new wxBitmap(image);
}
void ImageWindow::OnPaint(wxPaintEvent &event)
{
wxPaintDC pdc(this);
if (potatoBitmap != nullptr)
{
pdc.DrawBitmap(*potatoBitmap, wxPoint(150, 100), true);
}
}
You are not specifying the index of the image in the constructor and that's why you see the default one as you can see in the wxWdigets documentation:
wxImage::wxImage ( const wxString & name,
wxBitmapType type = wxBITMAP_TYPE_ANY,
int index = -1
)
index Index of the image to load in the case that the image file contains multiple images. This is only used by GIF, ICO and TIFF handlers. The default value (-1) means "choose the default image" and is interpreted as the first image (index=0) by the GIF and TIFF handler and as the largest and most colourful one by the ICO handler.
But, you should also consider wxAnimationCtrl (see this sample)
Use wxAnimationCtrl for playing gif animations
or
Use extract each frame from the gif image and draw one by one using wxTimer.
Related
Using cppwinrt (standard C++, not C++/CX) how would you set the content of a Button to an image, programmatically? Has to be programmatically because cppwinrt does not yet support xaml, in which doing that is easy. Here's what I am trying, which results in a functional but empty button:
Button button = Button();
BitmapImage bitmapImage = BitmapImage();
Uri imageUri = Uri(L"ms-appx:///Assets/Images/stopbutton.png");
bitmapImage.UriSource(imageUri);
Image buttonImage = Image();
buttonImage.Height(30);
buttonImage.Width(30);
buttonImage.Source(bitmapImage);
button.Content(buttonImage);
Then of course I add the button, which does show up nicely, though blank. I've tried an absolute path for the .png, but that also fails. There must be a way to do this programmatically in C++.
Your original code works fine on my side. Just make sure that your image really is inside the Assets/Images folder, that you added it to your project and that it is copied with the app content during the build, by checking if the Content parameter in the image properties is set to True.
Edit
After reading your further requirements. Just set the button padding and border thickness to zero, this will remove any space around the image.
Here is a simple working application with your button creation code:
#include <winrt\Windows.ApplicationModel.Activation.h>
#include <winrt\Windows.Devices.Enumeration.h>
#include <winrt\Windows.Foundation.h>
#include <winrt\Windows.UI.Xaml.h>
#include <winrt\Windows.UI.Xaml.Controls.h>
#include <winrt\Windows.UI.Xaml.Media.Imaging.h>
using namespace winrt;
using namespace winrt::Windows::ApplicationModel::Activation;
using namespace winrt::Windows::Devices::Enumeration;
using namespace winrt::Windows::Foundation;
using namespace winrt::Windows::UI::Xaml;
using namespace winrt::Windows::UI::Xaml::Controls;
using namespace winrt::Windows::UI::Xaml::Media::Imaging;
struct App : ApplicationT<App>
{
void OnLaunched(LaunchActivatedEventArgs const &)
{
Image image;
image.Height(30);
image.Width(30);
image.Source(BitmapImage(Uri(L"ms-appx:///Assets/Images/sample.png")));
Button button;
button.Padding(ThicknessHelper::FromUniformLength(0));
button.BorderThickness(ThicknessHelper::FromUniformLength(0));
button.Content(image);
Window window = Window::Current();
window.Content(button);
window.Activate();
}
static void Initialize(ApplicationInitializationCallbackParams const &)
{
make<App>();
}
static void Start()
{
Application::Start(App::Initialize);
}
};
int WINAPI wWinMain(HINSTANCE, HINSTANCE, PWSTR, int)
{
App::Start();
}
OK, here is what is needed to make a button display an image that fills the button: rather than setting the button.Content to an image, create an ImageBrush with the image and set the button.Background to that ImageBrush, e.g.
Button button = Button();
button.Height(30);
button.Width(30);
BitmapImage bitmapImage = BitmapImage();
Uri imageUri = Uri(L"ms-appx:///Assets/Images/stopbutton.png");
bitmapImage.UriSource(imageUri);
ImageBrush imageBrush = ImageBrush();
imageBrush.ImageSource(bitmapImage);
button.Background(imageBrush);
//The button will now look exactly like the image.
I want to have a button in my (iOS) app that takes a screenshot of the current screen and then attaches it to a text message.
Like I have seen in this other app...
I have message sending working, and I think I have screenshot working, but I don't know where the screenshot is saved or how to use it.
My message sending is called from a button in the app...
void GameOverScene::messageCallBack(cocos2d::Ref *sender) {
CocosDenshion::SimpleAudioEngine::getInstance()->playEffect(ALL_BUTTONS_CLICK_SOUND_NAME);
utils::captureScreen( CC_CALLBACK_2(GameOverScene::afterCaptured, this), "screenshot.png" );
__String *messageTextOne = __String::create("sms:&body=Hey,%20I%20just%20hit%20a%20score%20of%20");
__String *messageTextTwo = __String::createWithFormat("%i", score);
__String *messageURL = __String::createWithFormat("%s%s", messageTextOne->getCString(), messageTextTwo->getCString());
Application::getInstance()->openURL(messageURL->getCString());
}
and the screenshot function is...
void GameOverScene::afterCaptured( bool succeed, const std::string &outputFile ) {
if (succeed) {
log("Screen capture succeeded");
Size screenSize = Director::getInstance()->getWinSize();
RenderTexture * tex = RenderTexture::create(screenSize.width, screenSize.height);
tex->setPosition(screenSize.width/2, screenSize.height/2);
tex->begin();
this->getParent()->visit();
tex->end();
tex->saveToFile("Image_Save.png", Image::Format::PNG);
} else {
log("Screen capture failed");
}
}
I get the message in the console "Screen capture succeeded", and my message app opens up with the prefilled text message.
What I need to do is to add the screenshot to this message, but I cant see how to do that, or where the screenshot is saved, or how to use the saved screenshot.
If it succeeded it's saved in private application directory. Use software like iExplorer, find your app and it should be inside Documents directory. If you want to see it in Photos you have manually add it there.
In order to achieve this, you have to call
UIImageWriteToSavedPhotosAlbum
see: How to save picture to iPhone photo library?
You have to create a function in AppController.m and use it from here. You can call objc code from c++. It requires UIImage so first you have to pass filepath and load uiimage from it and then finally add to gallery.
You can use something like this to get the path of image saved:
void CustomLayerColor::saveFile(Node*node, std::string fileName, const renderTextureCallback& callBack) {
float renderTextureWidth = node->getBoundingBox().size.width;
float renderTextureHeight = node->getBoundingBox().size.height;
RenderTexture * renderTexture = RenderTexture::create(renderTextureWidth,renderTextureHeight);
renderTexture->begin();
node->visit();
renderTexture->end();
renderTexture->saveToFile(fileName, Image::Format::PNG, true,callBack);
}
void CustomLayerColor::onSaveFileCallBack(RenderTexture * mRenderTexture, const std::string& savedFileNameWithFullPath) {
}
I am writing a Maya C++ plugin that needs to get access to the imageFile that is loaded in the current imagePlane. I've got the plugin written, and I am able to iterate successfully through the imagePlanes, but I don't know how to get the imageFile that is loaded on the imagePlane. I have written a plugin that has a callback for the scene being loaded, and I'm that successfully iterateing through the imagePlanes, but how do I proceed from there to get the filename of the image loaded into the imagePlane? Here's a portion of my code for the sceneLoaded callback:
void MayaExtractCalDataPlugin::sceneLoaded( void* clientData )
{
// Store the pointer to the current class
MayaExtractCalDataPlugin* crntPlugin = (MayaExtractCalDataPlugin*)clientData;
// We only enter the callback when isReadingFile() is false, as this indicates that all
// loading is complete. otherwise we would enter a whole series of callbacks when loading a scene
// with lots of references in.
if( !MFileIO::isReadingFile() )
{
// Traverse the scene and find image planes
// First we need to create an iterator to go through all image planes
MItDependencyNodes it(MFn::kImagePlane);
//iterate through all image planes
while(!it.isDone())
{
// Get the imagePlane object
MStatus status;
MObject object = it.thisNode(&status);
...
}
}
}
But, now that I have the MObject and I know its an imagePlane, I don't know how to get to the imageFile that is loaded into it. Thanks in advance for any help you can offer!
I figured it out! I just needed to add the following statements after the above code, and I can access all the imagePlane methods and attributes:
// attach a dependency node to the file node
MFnDependencyNode fn(object);
// get the attribute for the imageName path
MPlug imagePath = fn.findPlug("imageName");
I am trying to add texts to images in Magick++ by doing so:
Method 1:
Magick::Image image(Magick::Geometry(800,800),Magick::Color("white"));
Magick::Color color(0,0,0,0);
image.font("Waree");
image.fontPointsize(36);
image.strokeColor(color);
image.fillColor(color);
image.annotate("HelloWorld!", NorthWestGravity);
Method 2:
Magick::Image image(Magick::Geometry(800,800),Magick::Color("white"));
Magick::Color color(0,0,0,0);
std::list<Magick::Drawable> text_draw_list;
text_draw_list.push_back(Magick::DrawableViewbox(0,0,image.columns(), image.rows()));
text_draw_list.push_back(Magick::DrawableFont("Waree", (Magick::StyleType)NormalStyle, 400, (Magick::StretchType)NormalStretch ));
text_draw_list.push_back(Magick::DrawablePointSize(36));
//Manual offsets
text_draw_list.push_back(Magick::DrawableText(0, 200, "HelloWorld!"));
text_draw_list.push_back(Magick::DrawableStrokeColor(color));
text_draw_list.push_back(Magick::DrawableFillColor(color));
image.draw(text_draw_list);
Method 1 calculates best offsets given the gravity but does not have any word wrapping if the text is out of bounds of the image.
Method 2 has Method 1's problem plus it assumes that the correct offsets have been calculated so the text is written at the correct position.
How do I add automatic word wrapping to either of the 2 methods but preferably to method 1?
P.S: ImageMagick has automatic word wrapping by using the caption option but I couldn't find caption in Magick++.
Edit: Ugly boundary control based on font size.
Magick::Image image(Magick::Geometry(800,800),Magick::Color("white"));
Magick::Color color(0,0,0,0);
image.font("Waree");
image.fontPointsize(36);
image.strokeColor(color);
image.fillColor(color);
std::string txt = "HelloWorld!";
Magick::TypeMetric typeMetrics;
double fontSize = 36;
image.fontTypeMetrics(txt, &typeMetrics);
while(fontSize > 0)
{
if(typeMetrics.textWidth() >= image.columns() || typeMetrics.textHeight() >= image.rows())
{
fontSize--;
image.fontTypeMetrics(txt, &typeMetrics);
}
}
image.annotate(txt, NorthWestGravity);
The best thing to do is read the caption.c source, and understand how word-wrapping is implemented. This would allow your application to have full control.
Another options would be to use PANGO: protocol. This would allow your content-author to have full control of word-wrapping, format, and many other font-display features.
But for the quickest approach, as you mentioned, caption already does this. But caption is not a method, but a file protocol.
#include <Magick++.h>
using namespace Magick;
int main(int argc, const char * argv[]) {
InitializeMagick(argv[0]);
Image words(Geometry(250,250), Color("white"));
words.backgroundColor(Color("lime")); // might not be needed.
words.font("Avenir-Heavy");
words.fillColor(Color("firebrick"));
words.strokeColor(Color("yellow"));
words.read("CAPTION:Hello World!"); // <---- CAPTION: protocol
words.write("/tmp/words.jpg");
return 0;
}
Good day! If you are lazy, you can try read only highlighted words:)
Source files .doc and .xls
I have the word document colors.doc. It's containing a picture 325x125 with extension png and it's display 44% zoom of full size.
I copy(Ctrl+C) this picture and paste(Ctrl+V) at car.xls. The picture is pasted with 44% zoom and I set it 100%. Then I close and save both documents.
The program:
I have a program, which open colors.doc and copy picture to clipboard using:
Shapes.Item(1).Select
Selection.CopyAsPicture
Program gets it from Clipboard like a EnhMetaFile (HENHMETAFILE). And when I play that metafile I get a good picture without smoothing. Program store this picture and close colors.doc. Then it open car.xls and copy picture to clipboard using:
Shapes.Item(1).CopyPicture(xlSreen, xlPicture) //default parameters
and my program again gets it like a EnhMetaFile (HENHMETAFILE). But when I play this metafile I get smoothed picture 407x156.
Why it happens? How I can avoid this? Help, please I can't decide this trouble already 2 days.
Some of my observations:
If I copy(Ctrl+C) picture from car.xls and paste(Ctrl+V) it to any graphical editor I get a good picture!!
Cod:
If you are not fear WINAPI and Ole see next code please:
Picture::InitFromBuffer(){
OpenClipboard(DebHDlg);
HENHMETAFILE emfp = (HENHMETAFILE)GetClipboardData(CF_ENHMETAFILE);
memset(&head, 0, sizeof(ENHMETAHEADER));
head.nSize = sizeof(ENHMETAHEADER);
GetEnhMetaFileHeader(emfp, sizeof(ENHMETAHEADER), &head);
data = new BYTE[head.nBytes];
GetEnhMetaFileBits(emfp, sizeof(BYTE)*(head.nBytes), data);
CloseClipboard();
}
Picture::Display(HWND hDlg){
if (hDlg != NULL){
HDC hDC = GetDC(DebHDlg);
int er;
RECT r;
HENHMETAFILE emfp = SetEnhMetaFileBits(this->head.nBytes, this->data);
GetClientRect(DebHDlg, &r);
if (!PlayEnhMetaFile(hDC, emfp, &r))
er = GetLastError();
ReleaseDC(hDlg, hDC);
}
}
struct Picture{
ENHMETAHEADER head;
BYTE *data;
...
};
I'm display it directly on main window for fast debug:)
Left picture is good. Right picture is smoothed.
I had the same problem but solved it by using Shapes.Item(1).Copy(...) instead of CopyPicture.