How to permanently scale an ImageMagick++ image on Ubuntu? - c++

I have an ImageMagick++ image that I'd like to scale to whatever width and height I like, and then I'd like to get access to the pixels of this new scaled image.
I want the scale operation to permanently alter the image. So far there are four ImageMagick++ methods that sound like they might achieve this scaling operation: resize(), sample(), scale(), and transform(), but the only one that I can get to almost work is sample().
The problem is that when I call tMyImage.sample() and then read the pixel values, the image is only scaled to the height that I pass to it and then the width is set according to the original aspect ratio.
Here's the code I'm using:
Magick::Image tMyIMage(iOriginalWidth, iOriginalHeight, "BGRA", Magick::CharPixel, (void *)pSourceData);
try { tImage.sample(Magick::Geometry(200, 50, 0, 0)); }
catch { Magick::Exception &eException)
{
// This never happens...
}
tImage.modifyImage();
size_t nNewWidth = tImage.columns();
size_t nNewHeight = tImage.rows();
// At this point I would expect that nNewWidth is 200 and nNewHeight is 50
// Instead, nNewHeight is 50 but nNewWidth is scaled according to the original aspect ratio
// Note here that tImage.baseColumns() and tImage.baseRows() both return 0
tImage.type(Magick::TrueColorType);
const Magick::PixelPacket *pPixels = tImage.getConstPixels(0, 0, nNewWidth, nNewHeight);
// Here I would expect that pPixels points to pixel data of a 200x50 pixel image
I am new to ImageMagick++ so I'm sure that I must be doing something wrong. Any help is greatly appreciated! Thanks!

I found out the reason that the scaling wasn't working; apparently the default in ImageMagick++ is to not take the exact dimensions you're using if the resulting aspect ratio would change -_-
You have to explicitly tell ImageMagick++ to take the exact dimensions when creating the geometry:
char szGeometry[64];
memset(&(szGeometry[0]), 0, sizeof(szGeometry));
snprintf(szGeometry, sizeof(szGeometry) - 1, "%ix%i!", iWidth, iHeight);
Magick::Image tScaled(iOriginalWidth, iOriginalHeight, "BGRA", Magick::CharPixel, (void *)pSourceData);
try { tScaled.sample(Magick::Geometry(szGeometry)); }
catch (Magick::Exception &eException)
{
...
}

Related

Fullscreen mode in processing

I'm making a little game in Processing. But I don't know how to set the coordinates to be the same on every monitor type using fullscreen. Like in a big monitor the coordinates are different from a smaller monitor.
I tried to translate the center to the middle of the screen!
Can anyone help me?
It sounds like you're using absolute coordinates, like this:
void setup(){
size(500, 500);
}
void draw(){
ellipse(250, 250, 400, 400);
}
This code draws a large circle in the middle of the screen. The problem is, this code does not consider the size of the window at all. So if you make it fullscreen, the circle keeps the same size and location.
Instead, you can use the width and height variables to make your drawing scale with the window:
void setup(){
size(500, 500);
}
void draw(){
ellipse(width / 2, height / 2, width * .8, height * .8);
}
Now the drawing will scale with the size of the window.
However, now you have a different problem: the drawing can get stretched out depending on the size of your monitor. You need to fix the aspect ratio. I'd recommend Googling that to see a ton of approaches, but for this simple example, you could just take the minimum of width and height and use that:
void setup() {
fullScreen();
}
void draw() {
float minDimension = min(width, height);
ellipse(width / 2, height / 2, minDimension * .8, minDimension * .8);
}
There are a ton of other ways to approach this. You could also look into using a PGraphics that's always the same size, and then scaling that depending on the screen size.
Shameless self-promotion: here and here are tutorials on using the width and height variables to scale your drawings.

Is there a way to save a Graphics object in Codename One without without taking a screenshot?

The question is in the title. For example how can I save g in a file in the following snippet ?
public void paints(Graphics g, Image background, Image watermark, int width, int height) {
g.drawImage(background, 0, 0);
g.drawImage(watermark, 0, 0);
g.setColor(0xFF0000);
// Upper left corner
g.fillRect(0, 0, 10, 10);
// Lower right corner
g.setColor(0x00FF00);
g.fillRect(width - 10, height - 10, 10, 10);
g.setColor(0xFF0000);
Font f = Font.createTrueTypeFont("Geometos", "Geometos.ttf").derive(220, Font.STYLE_BOLD);
g.setFont(f);
// Draw a string right below the M from Mercedes on the car windscreen (measured in Gimp)
g.drawString("HelloWorld",
(int) (848 ),
(int) (610)
);
// NOW how can I save g in a file ?
}
The reaseon why I don't want to take a screenshot is because I want to keep the full resolution of g (eg : 2000 x 1500).
I would be so grateful to anyone that can tell me how to do that with Codename one. If not possible then it is already good to know it!
Cheers,
What you could do is to create an Image as buffer, get the graphics object from the image an do all your drawings operations on it. Then draw the whole image to the display and save it as a file:
int height = 2000;
int width = 1500;
float saveQuality = 0.7f;
// Create image as buffer
Image imageBuffer = Image.createImage(width, height, 0xffffff);
// Create graphics out of image object
Graphics imageGraphics = imageBuffer.getGraphics();
// Do your drawing operations on the graphics from the image
imageGraphics.drawWhaterver(...);
// Draw the complete image on your Graphics object g (the screen I guess)
g.drawImage(imageBuffer, w, h);
// Save the image with the ImageIO class
OutputStream os = Storage.getInstance().createOutputStream("storagefilename.png");
ImageIO.getImageIO().save(imageBuffer, os, ImageIO.FORMAT_PNG, saveQuality);
Note, that I have not tested it, but it should work like that.
Graphics is just a proxy to a surface, it has no knowledge or access to the underlying surface to which it is drawing and the reason for that is quite simple. It can draw to a hardware accelerated "surface" where there is physically no underlying image.
This is the case both on iOS and Android where the "screen" is natively drawn and has no buffer.

How to Reduce the noisy While Scale a Image/Picture with Qt

I use the code just like:
void MyLabel::paintEvent(QPaintEvent *event){
QPainter painters(this);
/*对img进行平滑缩放*/
int image_width,image_height;
image_width = width();
image_height = height();
QImage result = img.scaled(image_width<<2,
image_height<<2).scaled(image_width,
image_height,Qt::IgnoreAspectRatio,Qt::SmoothTransformation
);
painters.drawPixmap(0,0,image_width,image_height,QPixmap::fromImage(img));
}
I want to scale a image to the size what I want, but when I scale it to Non equal proportion , terrible things happened ,noisy is huge ,and the image/picture just like this:
And i want to know how to get a way scale a image/picture like this instead:
I suspect it is because you call QImage::scaled() twice, first to upscale to 4× the desired size and second to your actual desired size. The first call uses the default value for the transformation mode (which is Qt::FastTransformation). So essentially you're combining a non-smooth and a smooth transformation. Note that the first transformation should be unnecessary anyway. Just scale to the desired size immediately, using Qt::SmoothTransformation.
QImage result = img.scaled(image_width, image_height,
Qt::IgnoreAspectRatio,
Qt::SmoothTransformation);
EDIT: Just noticed something else. Look at your drawPixmap line:
painters.drawPixmap(0,0,image_width,image_height,QPixmap::fromImage(img));
You're drawing the original img when you meant to draw result:
painters.drawPixmap(0,0,image_width,image_height,QPixmap::fromImage(result));

How to change an images size in c++, SDL

How can I change the images size in the code below:
const int XHome = 10, YHome = 10;
const int WHome = 50, HHome = 50;
.
.
.
SDL_Surface* Image = SDL_LoadBMP(Address);
SDL_Rect destRect;
destRect.x = WHome * x;
destRect.y = HHome * y;
destRect.w = WHome;
destRect.h = HHome;
SDL_BlitSurface(Image, NULL, mainScreen, &destRect);
SDL_FreeSurface(Image);
When I put Image in mainScreen which is another SDL_Surface, It's bigger than 50*50. Is it possible to resize Image? Thank you.
this is what happens when I set the WHome and HHome, 50*50.
Since I have only 5 reputation, I can't post images. To see the image please click here.
But when I set them like the original images size, this is what I see:
here
According to the SDL_BlitSurface documentation:
Only the position is used in the dstrect (the width and height are ignored).
I highly recommend switching to SDL 2 for many reasons (hardware acceleration being a big one); this task would also become trivial with a texture and SDL_RenderCopy. If you're somehow stuck using SDL 1, you can either look into scaling surfaces manually, or use a library like SDL_gfx, which has custom blit functions.

Store ID2D1Effect output in ID2D1Bitmap/Image to draw it at a later time?

i want to convert the output image of an ID2D1Effect to an ID2D1Bitmap, so I'm able to draw it at a later time without applying all the effects over and over...
My first try was just to keep the ID2D1Effect::GetOutput image ptr, but this image changes if I use the effect with another image source...
My next try was to create a Bitmap (ID2D1DeviceContext::CreateBitmap) with D2D1_BITMAP_OPTIONS_TARGET flag set and draw the effects output to this Bitmap but that doesn't seem to work either...
Draw effect to given Bitmap1** (dest):
ComPtr<ID2D1Image> swapChainImageBuffer;
this->pDeviceContext->CreateBitmap(D2D1::SizeU(120, 50), nullptr, 0, D2D1::BitmapProperties1(D2D1_BITMAP_OPTIONS_TARGET), dest);
this->pDeviceContext->GetTarget(swapChainImageBuffer.GetAddressOf());
this->pDeviceContext->SetTarget(*dest);
this->pDeviceContext->BeginDraw();
this->pDeviceContext->Clear(D2D1::ColorF(RGB(0, 0, 0), 1.f));
this->pDeviceContext->DrawImage(this->pCompositeEffect.Get(), D2D1::Point2F(20, 10));
this->pDeviceContext->EndDraw();
this->pDeviceContext->SetTarget(swapChainImageBuffer.Get());
swapChainImageBuffer = nullptr;
Draw the bitmap at a later time : (preview)
this->pD2DeviceContext->DrawBitmap(preview.Get(), D2D1::RectF(x, y, x+width, y + height));
(Same DeviceContext - no function that returns HRESULT returns an error code)
What am I doing wrong?
How am I supposed to do this?
simply forgot to specify the PixelFormat in CreateBitmap.
D2D1::PixelFormat(DXGI_FORMAT_B8G8R8A8_UNORM, D2D1_ALPHA_MODE_PREMULTIPLIED)
works now.