SDL_surface that contains several images - c++

Suppose I have a SDL_Surface that is just one image.
What if I wanted to make that SDL_Surface have three copies of that image, one below the other?
I came up with this function, but it doesn't show anything:
void ElementView::adjust()
{
int imageHeight = this->img->h;
int desiredHeight = 3*imageHeight;
int repetitions = desiredHeight / imageHeight ;
int remainder = desiredHeight % imageHeight ;
SDL_Surface* newSurf = SDL_CreateRGBSurface(img->flags, img->w, desiredHeight, 32, img->format->Rmask, img->format->Gmask, img->format->Bmask,img->format->Amask);
SDL_Rect rect;
memset(&rect, 0, sizeof(SDL_Rect));
rect.w = this->img->w;
rect.h = this->img->h;
for (int i = 0 ; i < repetitions ; i++)
{
rect.y = i*imageHeight;
SDL_BlitSurface(img,NULL,newSurf,&rect);
}
rect.y += remainder;
SDL_BlitSurface(this->img,NULL,newSurf,&rect);
if (newSurf != NULL) {
SDL_FreeSurface(this->img);
this->img = newSurf;
}
}

I think you should
Create a new surface that is 3 times as long as the initial one
Copy from img to the new surface using code similar to what you have (SDL_BlitSurface), except having the destination as your new surface
SDL_FreeSurface on your original img
Assign your new surface to img
Edit: Here is some sample code, didn't have time to test it though...
void adjust(SDL_Surface** img)
{
SDL_PixelFormat *fmt = (*img)->format;
SDL_Surface* newSurf = SDL_CreateRGBSurface((*img)->flags, (*img)->w, (*img)->h * 3, fmt->BytesPerPixel * 8, fmt->Rmask, fmt->Gmask, fmt->Bmask, fmt->Amask);
SDL_Rect rect;
memset(&rect, 0, sizeof(SDL_Rect));
rect.w = (*img)->w;
rect.h = (*img)->h;
int i = 0;
for (i ; i < 3; i++)
{
SDL_BlitSurface(*img,NULL,newSurf,&rect);
rect.y += (*img)->h;
}
SDL_FreeSurface(*img);
*img = newSurf;
}

Related

ucrtbased.dll: Access Violation

I am writing an extension (that is compiled as dynamic library), and I get extension error. Unfortunately, I have to draw entire GUI by myself, unfortunately, in pretty raw GDI/WinAPI.
This is my code that crashes:
Slider::Slider(const char* objectId, int height, POINT topLeft, int visibleElements, int totalElements, int elementHeight, EuroScopePlugIn::CRadarScreen* rs)
{
// Member variable initailization
m_ObjectId = objectId;
m_Height = height;
m_TopLeft = topLeft;
m_VisibleElements = visibleElements;
m_ElementHeight = elementHeight;
m_TotalElements = totalElements;
m_Width = 10;
m_pRS = rs;
m_CurrentFirstElement = 0;
m_CurrentLastElement = m_CurrentFirstElement + visibleElements;
}
SliderGrip::SliderGrip(Slider* sliderObject) : Slider(m_ObjectId.c_str(), m_Height, m_TopLeft, m_VisibleElements, m_TotalElements, m_ElementHeight, m_pRS)
{
// Base class member variable initialization
{
m_ObjectId = sliderObject->m_ObjectId;
m_Height = sliderObject->m_Height;
m_TopLeft = sliderObject->m_TopLeft;
m_VisibleElements = sliderObject->m_VisibleElements;
m_ElementHeight = sliderObject->m_ElementHeight;
m_TotalElements = sliderObject->m_TotalElements;
m_Width = sliderObject->m_Width;
m_pRS = sliderObject->m_pRS;
m_CurrentFirstElement = sliderObject->m_CurrentFirstElement;
m_CurrentLastElement = sliderObject->m_CurrentLastElement;
}
m_GripHeight = (m_VisibleElements / m_TotalElements) * m_ElementHeight;
m_GripTopLeft = (CPoint)(m_TopLeft.x, m_TopLeft.y + 10 + (m_CurrentFirstElement * m_ElementHeight));
}
void SliderGrip::RenderGrip(CDC* dc)
{
// localObjectId
std::string localObjectId = "Grip";
// Save DC for later
int sDC = dc->SaveDC();
// Create CRectangle
CRect CRectangle(m_GripTopLeft.x, m_GripTopLeft.y, m_GripTopLeft.x + m_Width, m_GripTopLeft.y + m_GripHeight);
// Grip Color
COLORREF m_GripColor = RGB(0, 0, 0);
// Fill CRectangle with CBrush
CBrush RectangleFill(m_GripColor);
dc->FillRect(&CRectangle, &RectangleFill);
m_pRS->AddScreenObject(CELEMENTS::SCROLLBAR_GRIP, localObjectId.c_str(), CRectangle, 1, "");
// Restore DC
dc->RestoreDC(sDC);
// Cleaning
DeleteObject(RectangleFill);
}
SliderTrack::SliderTrack(Slider* sliderObject) : Slider(m_ObjectId.c_str(), m_Height, m_TopLeft, m_VisibleElements, m_TotalElements, m_ElementHeight, m_pRS)
{
// Base class member variable initialization
{
m_ObjectId = sliderObject->m_ObjectId;
m_Height = sliderObject->m_Height;
m_TopLeft = sliderObject->m_TopLeft;
m_VisibleElements = sliderObject->m_VisibleElements;
m_ElementHeight = sliderObject->m_ElementHeight;
m_TotalElements = sliderObject->m_TotalElements;
m_Width = sliderObject->m_Width;
m_pRS = sliderObject->m_pRS;
m_CurrentFirstElement = sliderObject->m_CurrentFirstElement;
m_CurrentLastElement = sliderObject->m_CurrentLastElement;
}
m_TrackHeight = m_VisibleElements * m_ElementHeight;
m_TrackTopLeft = (CPoint)(m_TopLeft.x, m_TopLeft.y + 10);
}
void SliderTrack::RenderTrack(CDC* dc)
{
// Save DC for later
int sDC = dc->SaveDC();
// CRectangle
CRect CRectangle(m_TrackTopLeft.x, m_TrackTopLeft.y, m_TrackTopLeft.x + m_Width, m_TrackTopLeft.y + m_TrackHeight);
// Color
COLORREF m_TrackColor = RGB(200, 200, 200);
// Fill CRectangle with CBrush
CBrush RectangleFill(m_TrackColor);
dc->FillRect(&CRectangle, &RectangleFill);
// Restore DC
dc->RestoreDC(sDC);
// Cleaning
DeleteObject(RectangleFill);
}
SliderButton::SliderButton() : Slider(m_ObjectId.c_str(), m_Height, m_TopLeft, m_VisibleElements, m_TotalElements, m_ElementHeight, m_pRS)
{
}
[...]
#pragma region Scrollbar
// Scrollbar -> Elements::Slider --- grip, track, buttonup, buttondown
Scrollbar::Scrollbar(const char* name, EuroScopePlugIn::CRadarScreen* rs, POINT topLeft, int height, int visibleElements, int totalElements, int elementHeight)
{
// member Var initialization
m_Name = name;
m_pRS = rs;
m_TopLeft = topLeft;
m_Height = height;
m_Width = 10;
m_VisibleElements = visibleElements;
m_TotalElements = totalElements;
m_ElementHeight = elementHeight;
// initialize objects
sliderObject = new CInterface::Slider(m_Name.c_str(), m_Height, m_TopLeft, m_VisibleElements, m_TotalElements, m_ElementHeight, m_pRS);
gripObject = new CInterface::SliderGrip(sliderObject);
trackObject = new CInterface::SliderTrack(sliderObject);
}
void Scrollbar::AddTotalElements()
{
m_TotalElements++;
}
void Scrollbar::AddTotalElements(int count)
{
m_TotalElements += count;
}
void Scrollbar::RemoveTotalElements()
{
if(m_TotalElements>0)
m_TotalElements--;
}
void Scrollbar::RemoveTotalElements(int Count)
{
if (m_TotalElements > Count)
m_TotalElements -= Count;
}
void Scrollbar::Render(CDC* dc)
{
// for later
int sDC = dc->SaveDC();
gripObject->RenderGrip(dc);
trackObject->RenderTrack(dc);
// restore
dc->RestoreDC(sDC);
}
Scrollbar::~Scrollbar()
{
delete sliderObject;
delete gripObject;
delete trackObject;
}
#pragma endregion Scrollbar
Later on, code is called from main app in this way:
CallingFunction()
{
testScroll = new CInterface::Scrollbar("testScroll", this, xyz, 50, 10, 50, 5);
}
~CallingFunction()
{
delete testScroll;
}
Until now, code doesn't crash, but once I call rendering functions:
OnRender(HDC hDC)
{
CDC dc;
dc.Attach(hDC);
testScroll->Render(&dc);
dc.Detach();
dc.DeleteDC();
}
App crashes on startup with given code error:
Exception thrown at 0x78F6FF5C (ucrtbased.dll) in EuroScope.exe: 0xC0000005: Access violation reading location 0xCDCDCDCD.
I have no clue what's causing this, any ideas? I am roughly sure it may be issue with some pointer and/or passed const char*. While I tried to replace const char* to std::string whenever possible, I got an similar error, but related to vcruntime140.dll...

MFC CScrollView does not clear background

My English is not perfect. I am using Visual C++ 2019 and MFC. Example program: an SDI program, the base of the view is CScrollView, draws 128*128 0s in a matrix. But MFC does not clear the background at scrolling with the scrollbar. Have you an idea? Thank you.
In settings of Windows, I am using 96 dpi * 3 = 288 dpi.
I tried: 96 dpi mode is affected so.
How can I upload the example program to this?
void CsdView::OnDraw(CDC *pDC) {
CsdDoc *pDoc = GetDocument();
ASSERT_VALID(pDoc);
if (!pDoc)
return;
CRect rect;
GetClientRect(&rect);
pDC->FillSolidRect(rect, 0xFFFFFF);
CPoint pos = GetDeviceScrollPosition();
TRACE(L"OnDraw: %4u.%4u - %4u.%4u, %4u.%4u\n", rect.right, rect.bottom, pos.x, pos.y, rect.right + pos.x, rect.bottom+pos.y);
for (int i = 0; i < 128; ++ i)
for (int j = 0; j < 128; ++ j)
pDC->TextOutW(j*20 - pos.x, i*54 - pos.y, L"0", 1);
}
void CsdView::OnInitialUpdate() {
CScrollView::OnInitialUpdate();
CSize sizeTotal;
sizeTotal.cx = 20*128;
sizeTotal.cy = 54*128;
SetScrollSizes(MM_TEXT, sizeTotal);
}
BOOL CsdView::OnEraseBkgnd(CDC *pDC) {
CBrush brush(0xFFFFFF);
FillOutsideRect(pDC, &brush);
return TRUE;
// return CScrollView::OnEraseBkgnd(pDC);
}
I can not upload picture and code as a comment, so I must edit the original question.
A little bug is remained. The orginal code (MDI MFC):
void CIDEView::OnDraw(CDC *pDC) {
CIDEDoc *const d = GetDocument();
ASSERT_VALID(d);
if (! d)
return;
CPoint const pos = GetDeviceScrollPosition();
CRect rect;
GetClientRect(&rect);
OffsetRect(&rect, pos.x, pos.y);
pDC->FillSolidRect(rect, bkcolor);
auto oldfont = pDC->SelectObject(&font);
pDC->SetBkColor(bkcolor);
pDC->SetTextColor(textcolor);
pDC->SetBkMode(TRANSPARENT);
const int cxs = pos.x / mincw, cys = pos.y / lineheight;
const int cxe = (rect.right + mincw-1) / mincw,
cye = (rect.bottom + 41) / lineheight;
for (int i = cys; i <= cye; ++ i)
for (int j = cxs; j <= cxe; ++ j)
pDC->TextOutW(textmargin+j*mincw, i*lineheight, L"0", 1);
pDC->SelectObject(oldfont);
}
void CIDEView::OnInitialUpdate() {
CScrollView::OnInitialUpdate();
SetScrollSizes(MM_TEXT, {linewidth, 128*lineheight});
}
BOOL CIDEView::OnEraseBkgnd(CDC *pDC) {
return TRUE;
}
The CScrollView class is a view with scrolling capabilities. You use it almost like a CView (ie drawing in the OnDraw() member), only you have to take into account the possible scrolling.
The GetClientRect() function returns the visible client area, and the coordinates returned are not relative to the view origin, but to the window origin, ie the left and top members are always 0. The CDC parameter in the OnDraw() function though are relative to the logical view origin, so an adjustment is needed.
As for your code, you don't need to use the OnEraseBkgnd() function, because you do so in OnDraw(). You fill only the visible part of the window, but that's very much OK. So it would best to remove it. Also, the coordinates passed to the TextOutW() function must be relative to the view origin, so the -pos.x and -pos.y adjustments are wrong. Instead, it's the rectanlge passed to the FillSolidRect() function that needs to be adjusted. So, your code would become:
void CsdView::OnDraw(CDC *pDC)
{
CsdDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
if (!pDoc)
return;
CPoint pos = GetScrollPosition();
CRect rect;
GetClientRect(&rect);
// Adjust client rect to device coordinates
OffsetRect(&rect, pos.x, pos.y);
pDC->FillSolidRect(rect, 0xFFFFFF);
for (int i = 0; i < 128; ++i)
for (int j = 0; j < 128; ++j)
pDC->TextOutW(j * 20, i * 54, L"0", 1);
}
However this code is "wasteful", as it paints the whole view. It can be optimized to paint only the visible part. It will draw only the 0s for which even one pixel lies in the visible part (didn't #define anything, just used your hard-coded 20 and 54 values). Also changed the color to yellow, so you can test it better (white is the default background color).
void CsdView::OnDraw(CDC *pDC)
{
CsdDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
if (!pDoc)
return;
CPoint pos = GetScrollPosition();
CRect rect;
GetClientRect(&rect);
// Adjust client rect to device coordinates
OffsetRect(&rect, pos.x, pos.y);
pDC->FillSolidRect(rect, 0x00FFFF);
// Paint only the items in the visible part
int xL = rect.left / 20,
xR = (rect.right + 19) / 20,
yT = rect.top / 54,
yB = (rect.bottom + 53) / 54;
for (int i = yT; i < yB; ++i)
for (int j = xL; j < xR; ++j)
pDC->TextOutW(j * 20, i * 54, L"0", 1);
}
EDIT:
In the revised code, why are the doc, pos, cxs etc variables const? There are also quite a few bugs in your logic:
You set your view size in OnInitialUpdate(), rather assuming that linewidth equals to textmargin + 128*mincw. If not, revise your code again.
The rect is already adjusted (using OffsetRect()), so it is wrong to add pos.x again.
Since you have the cell sizes in variables, don't use hard-coded numbers. For example the code for cxe should become cxe = (rect.right + mincw - 1) / mincw; Update the cye code similarly.
Also you paint at an offset of textmargin. The code should then become cxe = (rect.right - textmargin + mincw - 1) / mincw;
The code I posted works OK with the < condition in the loops, you don't need <=. Do the math and you will find that this is the correct one.

Drawing a chess board with SDL2's SDL_RenderDrawRect

I am fairly new to SDL2 and as my first project I wanted to just create a chess board. This has proven to be harder than I thought.
I have tried lots of different ways to draw the fields of the chess board with SDL_RenderDrawRect, this is the current state:
#include <SDL2/SDL.h>
int main()
{
bool quit = false;
SDL_Event event;
SDL_Init(SDL_INIT_EVERYTHING);
SDL_Window *window = SDL_CreateWindow("Chess", SDL_WINDOWPOS_UNDEFINED,
SDL_WINDOWPOS_UNDEFINED, 680, 680, 0);
SDL_Renderer *render = SDL_CreateRenderer(window, -1,
SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);
for (int x = 0; x > 3; x++) {
for (int y = 0; x > 8; x++) {
SDL_Rect rect;
rect.x = x*10;
rect.y = y*10;
rect.w = 128;
rect.h = 128;
SDL_SetRenderDrawColor(render, 159, 84, 8, 255);
SDL_RenderFillRect(render, &rect);
}
}
SDL_RenderPresent(render);
while (!quit) {
SDL_WaitEvent(&event);
switch (event.type) {
case SDL_QUIT:
quit = true;
break;
}
}
SDL_Quit();
return 0;
}
No rectangles want to show up when I use SDL_RenderDrawRect in a loop. Any ideas why that is?
Cheers!
There are multiple errors in your for loops.
You have to change your conditions in your for loops. Both iteration variables(x and y) start with 0, but your condition to run the foor loop is that they are greater than 3 or 8, so they wont get executed. Change it to less than the value(< instead of >)
You have to change the iteration variable of your second for loop. You create y but the condition and the value change is for x
Your Rect is 128x128 big, but you multiply your x and y from your loops by 10, that means your Rectangles will overlap. You have to multiply it by at least 128.
If you look at a Chess Board, beginning at the top left and going from left to right, every second field is colored. To implement that you have to start in the top left corner, and iterate over every cell, and then jump to the next row. Every second field, you have to draw a Rect.
This is a slightly edited version of your algorithm:
int startPos = 0;
for (int y = 0; y < 8; y++) {
for (int x = startPos; x < 3; x+=2) {
SDL_Rect rect;
rect.x = x * 129;
rect.y = y * 129;
rect.w = 128;
rect.h = 128;
SDL_SetRenderDrawColor(render, 159, 84, 8, 255);
SDL_RenderFillRect(render, &rect);
}
startPos = 1 - startPos;
}
Explanation:
In the first row, the first field will be colored, because startPos is 0.
Since every row has the opposite start of its predecessor, we have to change startPos as soon as the last cell of a row is drawn.
Since we only need to draw every second cell, the x has to be increased by two every iteration
Hope this helped you a little bit
Although ur problem is solved, leaving this for someone who face such issue
(anyhow its quite easy to make the board, I wrote this code)
this will create a standard 8x8 chess board
void Create_Board() {
SDL_Rect Box = { 0,0,80,80}; COORD position = { 0 };
bool toggle_color = 0;
for (int i = 0; i < 8; i++)
{
for (int j = 0; j < 8; j++)
{
if (toggle_color)
SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
else
SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255);
SDL_RenderFillRect(renderer, &Box);
Box.x += 80;
if(j != 7) //needed for chess color pattern
toggle_color = !toggle_color;
}
Box.x = 0;
Box.y += 80;
}
}

Text overlay not working with Xorg modesetting driver

This is a piece of code which displays text and background rectangle When this piece of code is run with Intel as default XORG driver everything works fine both text and rectangle are being displayed,whereas when i switch to the Modesetting driver only the background rectangle is seen and text is not being displayed
#include <iostream>
#include<unistd.h>
#include <sstream>
#include <string>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/Xft/Xft.h>
#include <X11/extensions/XShm.h>
#include <sys/ipc.h>
#include <sys/shm.h>
using namespace std;
int main()
{
Display *display = XOpenDisplay(NULL);
Screen *scn = DefaultScreenOfDisplay(display);
int screen_num = DefaultScreen(display);
int screen_width = DisplayWidth(display, screen_num);
int screen_height = DisplayHeight(display, screen_num);
int defaultScnDepth = DefaultDepthOfScreen(scn);
Visual *visual = DefaultVisualOfScreen(scn);
Window window=XCreateSimpleWindow(display,RootWindow(display,screen_num), 50, 50, 400, 400, 2 ,BlackPixel(display,screen_num),WhitePixel(display,screen_num));
//XFlush(display)
XMapWindow(display, window);
XShmSegmentInfo shmInfo;
XImage *xImage;
Pixmap backPixmap;
(xImage) = XShmCreateImage(display, visual, defaultScnDepth, ZPixmap, NULL, &shmInfo, screen_width, screen_height);
shmInfo.shmid = shmget(IPC_PRIVATE, (xImage)->bytes_per_line * (xImage)->height, IPC_CREAT | 0777);
shmInfo.shmaddr = (char *) shmat(shmInfo.shmid, 0, 0);
xImage->data = shmInfo.shmaddr;
shmInfo.readOnly = False;
XShmAttach(display, &shmInfo);
(backPixmap) = XShmCreatePixmap(display, window, (char *) (shmInfo.shmaddr), &shmInfo, (xImage)->width, (xImage)->height, (xImage)->depth);
XGCValues values;
GC gc = XCreateGC(display, backPixmap, 0, &values);
XSync(display, false);
Drawable drawable =backPixmap;
visual = DefaultVisual(display, DefaultScreen(display));
Colormap colormap = XCreateColormap(display, window, visual, AllocNone);
//gc = XCreateGC(display, drawable, 0, &values);
//XFlushGC(display, gc);
const char *text = "Hello";
XftDraw *xftDraw = NULL;
XRenderColor xrFGColor, xrBGColor;
XftColor xftFGColor, xftBGColor;
XftFont *font = NULL;
font = XftFontOpenName( display, DefaultScreen( display ), "morpheus-18" );
xftDraw = XftDrawCreate(display, drawable, visual, colormap);
int nextLineStartY, rectYRef;
bool firstIte;
unsigned int rectX, rectY, rectWidth, rectHeight;
nextLineStartY = 0; rectYRef = 0;
firstIte = true;
rectX = 0; rectY = 0; rectWidth = 0; rectHeight = 0;
std::istringstream strStream(text);
std::string line;
while(std::getline(strStream, line))
{
const char *lineText = line.c_str();
if(*lineText == '\0')
{
nextLineStartY += rectHeight + 1;
continue;
}
const char *text = lineText;
XGlyphInfo extents;
XftTextExtents8(display, font, (XftChar8 *)text, strlen(text), &extents);
unsigned int width = extents.width;
unsigned int height = extents.height;
int ascent = extents.y;
int lBearing = extents.x;
rectX = 50 - lBearing - 1;
rectY = 50 - ascent - 1;
rectWidth = width + 2 * 1;
rectHeight = height + 5 + 1;
if(firstIte)
{
rectYRef = rectY;
firstIte = false;
}
int diff = rectYRef - rectY;
rectY += nextLineStartY + diff;
nextLineStartY += rectHeight + 1;
if(1)
{
xrBGColor.red = 0x7fff;
xrBGColor.green= 0x7fff;
xrBGColor.blue = 0x7fff;
xrBGColor.alpha= 0xffff;
XftColorAllocValue(display, visual, colormap, &xrBGColor, &xftBGColor);
// Draw background fill rectangle
XftDrawRect(xftDraw, &xftBGColor, rectX, rectY, rectWidth, rectHeight);
XftColorFree(display, visual, colormap, &xftBGColor);
}
xrFGColor.red = 0xbfff;
xrFGColor.green = 0xbfff;
xrFGColor.blue = 0xbfff;
xrFGColor.alpha= 0xffff;
XftColorAllocValue(display, visual, colormap, &xrFGColor, &xftFGColor);
// Overlay Text
XftDrawString8(xftDraw, &xftFGColor, font, 50, 50, (XftChar8 *) text, strlen(text));
XColor xForeColor;
xForeColor.red = 0xafff;
xForeColor.green = 0xafff;
xForeColor.blue = 0xffff;
if(XAllocColor(display,colormap,&xForeColor))
XSetForeground(display,gc,xForeColor.pixel);
XftColorFree(display, visual, colormap, &xftFGColor);
XFreeColors(display, colormap, &(xForeColor.pixel), 1, 0);
}
XftDrawDestroy(xftDraw);
XShmPutImage(display, window, gc, xImage, 0, 0, 0, 0, 400, 400, false);
XSync(display, false);
getchar();
}
I tried out other drivers too, with the radeon drivers i see a X error that shared pixmaps are not supported while i don't see any such error for the modesetting driver.
Has this something to do with the shared pixmaps, if yes how should i make it work with the modesetting driver.
I have been stuck on this for a while now, any help would be appreciated.

How do I get maximum centered rectangular area of Image in firemonkey c++

I'm trying to crop an image in a rectangular area, to fill a circle with it, but I cannot find any way to do that. Tt says that the result of my code is not correct and the image is not well placed. I don't know what is wrong in my code.
I saw some examples , but they are not working for me.
Here are the sites I visited:
crop and align inserted BMP in Delphi
https://www.experts-exchange.com/questions/22142653/Crop-Bitmap-Image1.html
Delphi - how do I crop a bitmap "in place"?
How to crop an FMX TBitmap
Note: the code should be wrote in FMX whit C++, it should run in all platforms.
The TCircle have the WrapMode assign to TileStrech.
void __fastcall TForm9::Button1Click(TObject *Sender)
{
int X , Y , W , H;
if(Image1->Bitmap->Width >= Image1->Bitmap->Height)
{
H = Image1->Bitmap->Height;
X = (Image1->Bitmap->Width - Image1->Bitmap->Height) / 2;
Y = 0;
W = H;
}
else
{
W = Image1->Bitmap->Width;
X = 0;
Y = (Image1->Bitmap->Width - Image1->Bitmap->Height) / 2;
H = W;
}
TRect rect(X, Y, W, H);
TBitmap * bm = new TBitmap(W,H);
bm->CopyFromBitmap(Image1->Bitmap ,rect ,X,Y);
Circle1->Fill->Bitmap->Bitmap->Assign(bm);
Image2->Bitmap->Assign(bm);
delete bm;
}
The result of this code is:
The bitmap is not well placed in a Circle
My objetive is get an crop image like this :
image croped
Solved
I have one solution for this problem
int CropBitmap(TBitmap* in, TBitmap* out)
{
if (!in or !out)
{
return 1;
}
TBitmap * bm = new TBitmap();
int origH = in->Height;
int origW = in->Width;
TRect rect;
int defH, defW;
if (origH > origW)
{
bm->Height = origW;
bm->Width = origW;
int factor = (origH - origW) / 2;
rect.Top = factor;
rect.Left = 0;
rect.Right = origW;
rect.Bottom = factor + origW;
bm->CopyFromBitmap(in, rect, 0, 0);
}
else if (origW > origH)
{
bm->Height = origH;
bm->Width = origH;
int factor = (origW - origH) / 2;
rect.Top = 0;
rect.Left = factor;
rect.Right = factor + origH;
rect.Bottom = origH;
bm->CopyFromBitmap(in, rect, 0, 0);
}
else
{
bm->Assign(in);
}
out->Assign(bm);
delete bm;
return 0;
}
It run well for me.