Essentially, I'm trying to go oldschool and make a lil 2D engine, but instead of just importing bmp's or other image files, i'm looking to print each pixel to the screen myself.

Firstly, Ive got it so I can display a single image I made, however, for colors such as dark red, they show up fine on a black background, but change the background colour and the darkred becomes pink or whatever, like the background is bleeding through.

Secondly, I doubt my method is the best method for what i'm trying to do, so aswell as a fix to the above problem, and suggestions would be welcome.

And finally, yes, my code is so unoptimised as to probably give you a migraine. I seriously need to go through it and clean it up. :)

main.cpp

#include <Windows.h>
#include <windowsx.h>

#include "system.h"

LRESULT CALLBACK wndProc(HWND hwnd, UINT uint, WPARAM wparam, LPARAM lparam);

int WINAPI WinMain(HINSTANCE hinstance, HINSTANCE hinstancePrev, LPSTR cmdLine, int cmdShow)
{
    gameSystem* sys;

    bool result;

    sys = new gameSystem;

    if (!sys)
        return false;

    result = sys->systemInit();

    if (result)
    {
        sys->systemRun();
    }

    sys->systemShutdown();
    delete sys;
    sys = 0;

    return 0;
}

----

system.h

#pragma once

#ifndef _GAMESYSTEM_
#define _GAMESYSTEM_

#define WIN32_LEAN_AND_MEAN

#include <Windows.h>
#include "game2D.h"

class gameSystem
{
public:
    gameSystem();
    gameSystem(const gameSystem&);
    ~gameSystem();

    bool systemInit();
    void systemShutdown();
    void systemRun();

    LRESULT CALLBACK MessageHandler(HWND, UINT, WPARAM, LPARAM);

private:
    bool systemFrame();
    bool initWindows(int&, int&);
    void shutdownWindows();

    LPSTR appName;
    HINSTANCE hInstance;
    HWND hwnd;
    bool fullscreen;
    game2D* lD2D;
};

static LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);

static gameSystem* appHandle = 0;

#endif

----

system.cpp

#include "system.h"
#include "game2D.h"



gameSystem::gameSystem()
{

}

gameSystem::gameSystem(const gameSystem& other)
{

}

gameSystem::~gameSystem()
{

}

bool gameSystem::systemInit()
{
//  HRESULT hr;

    int scrW, scrH;
    //bool result;

    scrW = 0;
    scrH = 0;
    fullscreen = 0;

    lD2D = new game2D();
    lD2D->game2DInit();


    if (!initWindows(scrW, scrH))
    {
        return false;
    }

    return true;
}

void gameSystem::systemShutdown()
{
    lD2D->game2DShutdown();
    shutdownWindows();

    return;
}

void gameSystem::systemRun()
{
    MSG msg;
    bool done, result;

    ZeroMemory(&msg, sizeof(MSG));

    done = false;

    while (!done)
    {
        if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
        {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }

        if (msg.message == WM_QUIT)
        {
            done = true;
        }
        else
        {
            result = systemFrame();
            if (!result)
            {
                done = true;
            }
        }
    }

    return;
}

bool gameSystem::systemFrame()
{
    lD2D->game2DRender();

    return true;
}

LRESULT CALLBACK gameSystem::MessageHandler(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
{
    switch (msg)
    {
    case WM_KEYDOWN:
    {
               return 0;
    }
    case WM_KEYUP:
    {
               return 0;
    }
    default:
    {
               return DefWindowProc(hwnd, msg, wparam, lparam);
    }
    }
}

bool gameSystem::initWindows(int& screenWidth, int& screenHeight)
{
    WNDCLASSEX wc;
    DEVMODE dmScreenSettings;
    int posX, posY;

    appHandle = this;

    hInstance = GetModuleHandle(NULL);

    appName = "Engine";

    wc.style = CS_HREDRAW | CS_VREDRAW;
    wc.lpfnWndProc = WndProc;
    wc.cbClsExtra = 0;
    wc.cbWndExtra = 0;
    wc.hInstance = hInstance;
    wc.hIcon = LoadIcon(NULL, IDI_WINLOGO);
    wc.hIconSm = wc.hIcon;
    wc.hCursor = LoadCursor(NULL, IDC_ARROW);
    wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 3);
    wc.lpszMenuName = NULL;
    wc.lpszClassName = appName;
    wc.cbSize = sizeof(WNDCLASSEX);

    RegisterClassEx(&wc);

    screenWidth = GetSystemMetrics(SM_CXSCREEN);
    screenHeight = GetSystemMetrics(SM_CYSCREEN);

    if (fullscreen)
    {
        memset(&dmScreenSettings, 0, sizeof(dmScreenSettings));
        dmScreenSettings.dmSize = sizeof(dmScreenSettings);
        dmScreenSettings.dmPelsWidth = (unsigned long)screenWidth;
        dmScreenSettings.dmPelsHeight = (unsigned long)screenHeight;
        dmScreenSettings.dmBitsPerPel = 32;
        dmScreenSettings.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;

        ChangeDisplaySettings(&dmScreenSettings, CDS_FULLSCREEN);

        posX = posY = 0;
    }
    else
    {
        screenWidth = 320;
        screenHeight = 240;

        posX = (GetSystemMetrics(SM_CXSCREEN) - screenWidth) / 2;
        posY = (GetSystemMetrics(SM_CYSCREEN) - screenHeight) / 2;


    }

    hwnd = CreateWindowEx(NULL, appName, appName, WS_OVERLAPPEDWINDOW, posX, posY, screenWidth, screenHeight, NULL, NULL, hInstance, NULL);

    ShowWindow(hwnd, SW_SHOW);
    SetForegroundWindow(hwnd);
    SetFocus(hwnd);
    /*ShowCursor(false);*/

    //if (!dxEng->initDX(hInstance, screenWidth, screenHeight, hwnd))
    //{
    //  return false;
    //}
    lD2D->game2DCreateDevice(hwnd);
    lD2D->game2DResize(screenWidth, screenHeight);
    return true;
}


void gameSystem::shutdownWindows()
{
    ShowCursor(true);

    delete lD2D;
    lD2D = 0;

    if (fullscreen)
    {
        ChangeDisplaySettings(NULL, 0);
    }

    DestroyWindow(hwnd);
    hwnd = NULL;

    UnregisterClass(appName, hInstance);
    hInstance = NULL;

    appHandle = NULL;

    return;
}

LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
{
    switch (msg)
    {
    case WM_DESTROY:
    {
                       PostQuitMessage(0);
                       return 0;
    }
    case WM_CLOSE:
    {
                     PostQuitMessage(0);
                     return 0;
    }

    default:
    {
               return appHandle->MessageHandler(hwnd, msg, wparam, lparam);
    }
    }
}

----

game2d.h

#pragma once
#include <d2d1.h>
#include <d2d1helper.h>
#include <string>
#include <vector>


struct pixelImage
{

    int rows;
    int cols;
    std::vector <float> dataStore;

};


class game2D
{
public:
    game2D();
    ~game2D();

    HRESULT game2DInit();
    void game2DRender();
    void game2DResize(UINT width, UINT height);

    D2D1_RECT_F setPixel(UINT xCoord, UINT yCoord, float red, float blue, float green, float alpha);

    void loadAsset();

    void convertTo();

    HRESULT game2DCreateDevice(HWND localHWND);
    void game2DShutdown();

private:
    bool CDevComplete;

    std::vector <char> tempStore;
    pixelImage pxImage;
    std::string fileContents;

    long filesize;
    int storeSize;

    ID2D1Factory*   D2DFactory;
    ID2D1HwndRenderTarget*  D2DRenderTarget;
    ID2D1SolidColorBrush*   D2DColorBrush;
    ID2D1LinearGradientBrush*   D2DGradientBrush;
};

----

game2d.cpp

#include "game2D.h"
#include <fstream>
#include <string>
#include <vector>
#include <sstream>

#pragma comment( lib, "d2d1.lib" )

game2D::game2D()
{
    D2DFactory = NULL;
    D2DRenderTarget = NULL;
    D2DColorBrush = NULL;
    D2DGradientBrush = NULL;

    CDevComplete = false;
}

/*game2D::game2D(const game2D&)
{

}*/

game2D::~game2D()
{

}

HRESULT game2D::game2DInit()
{
    HRESULT hr;

    hr = D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, &D2DFactory);

    return hr;
}

void game2D::game2DResize(UINT width, UINT height)
{
    if (D2DRenderTarget)
    {
        D2DRenderTarget->Resize(D2D1::SizeU(width, height));
    }
}

D2D1_RECT_F game2D::setPixel(UINT xCoord, UINT yCoord, float red, float blue, float green, float alpha)
{
    D2D1_RECT_F local;


    local = D2D1::RectF(
        xCoord - 0.0f,
        yCoord - 0.0f,
        xCoord + 1.0f,
        yCoord + 1.0f
        );

    D2DRenderTarget->CreateSolidColorBrush(D2D1::ColorF(D2D1::ColorF(red, blue, green, alpha)), &D2DColorBrush);

    return local;
}

void game2D::convertTo()
{
    bool endLine = false;
    bool deci = false;

    int dataCount = 0;
    int startCount = 0;

    int trueCount = 0;

    pxImage.dataStore.resize(filesize);

    for (int i = 0; i < filesize; i++)
    {
        switch (tempStore[i])
        {
            if (endLine == true) endLine = false;

            case 44: // ,
                endLine = true;
                dataCount++;
                break;
            case 46: // .
                deci = true;
                break;
            case 48: // 0
                if (startCount == 0) {
                    pxImage.cols = 0;
                    startCount++;
                }
                else if (startCount == 1) {
                    pxImage.rows = 0;
                    startCount++;
                }
                else {
                    if (deci == true) {
                        pxImage.dataStore[dataCount] = (float)0.0;
                        trueCount--;
                        deci = false;
                    }
                    else {
                        pxImage.dataStore[dataCount] = 0;
                        trueCount++;
                    }
                }
                break;
            case 49: // 1
                if (startCount == 0) {
                    pxImage.cols = 1;
                    startCount++;
                }
                else if (startCount == 1) {
                    pxImage.rows = 1;
                    startCount++;
                }
                else {
                    if (deci == true) {
                        pxImage.dataStore[dataCount] = (float)0.1;
                        trueCount--;
                        deci = false;
                    }
                    else {
                        pxImage.dataStore[dataCount] = 1;
                        trueCount++;
                    }
                }
                break;
            case 50: // 2
                if (startCount == 0) {
                    pxImage.cols = 2;
                    startCount++;
                }
                else if (startCount == 1) {
                    pxImage.rows = 2;
                    startCount++;
                }
                else {
                    if (deci == true) {
                        pxImage.dataStore[dataCount] = (float)0.2;
                        trueCount--;
                        deci = false;
                    }
                    else {
                        pxImage.dataStore[dataCount] = 2;
                        trueCount++;
                    }
                }
                break;
            case 51: // 3
                if (startCount == 0) {
                    pxImage.cols = 3;
                    startCount++;
                }
                else if (startCount == 1) {
                    pxImage.rows = 3;
                    startCount++;
                }
                else {
                    if (deci == true) {
                        pxImage.dataStore[dataCount] = (float)0.3;
                        trueCount--;
                        deci = false;
                    }
                    else {
                        pxImage.dataStore[dataCount] = 3;
                        trueCount++;
                    }
                }
                break;
            case 52: // 4
                if (startCount == 0) {
                    pxImage.cols = 4;
                    startCount++;
                }
                else if (startCount == 1) {
                    pxImage.rows = 4;
                    startCount++;
                }
                else {
                    if (deci == true) {
                        pxImage.dataStore[dataCount] = (float)0.4;
                        trueCount--;
                        deci = false;
                    }
                    else {
                        pxImage.dataStore[dataCount] = 4;
                        trueCount++;
                    }
                }
                break;
            case 53: // 5
                if (startCount == 0) {
                    pxImage.cols = 5;
                    startCount++;
                }
                else if (startCount == 1) {
                    pxImage.rows = 5;
                    startCount++;
                }
                else {
                    if (deci == true) {
                        pxImage.dataStore[dataCount] = (float)0.5;
                        trueCount--;
                        deci = false;
                    }
                    else {
                        pxImage.dataStore[dataCount] = 5;
                        trueCount++;
                    }
                }
                break;
            case 54: // 6
                if (startCount == 0) {
                    pxImage.cols = 6;
                    startCount++;
                }
                else if (startCount == 1) {
                    pxImage.rows = 6;
                    startCount++;
                }
                else {
                    if (deci == true) {
                        pxImage.dataStore[dataCount] = (float)0.6;
                        trueCount--;
                        deci = false;
                    }
                    else {
                        pxImage.dataStore[dataCount] = 6;
                        trueCount++;
                    }
                }
                break;
            case 55: // 7
                if (startCount == 0) {
                    pxImage.cols = 7;
                    startCount++;
                }
                else if (startCount == 1) {
                    pxImage.rows = 7;
                    startCount++;
                }
                else {
                    if (deci == true) {
                        pxImage.dataStore[dataCount] = (float)0.7;
                        trueCount--;
                        deci = false;
                    }
                    else {
                        pxImage.dataStore[dataCount] = 7;
                        trueCount++;
                    }
                }
                break;
            case 56: // 8
                if (startCount == 0) {
                    pxImage.cols = 8;
                    startCount++;
                }
                else if (startCount == 1) {
                    pxImage.rows = 8;
                    startCount++;
                }
                else {
                    if (deci == true) {
                        pxImage.dataStore[dataCount] = (float)0.8;
                        trueCount--;
                        deci = false;
                    }
                    else {
                        pxImage.dataStore[dataCount] = 8;
                        trueCount++;
                    }
                }
                break;
            case 57: // 9
                if (startCount == 0) {
                    pxImage.cols = 9;
                    startCount++;
                }
                else if (startCount == 1) {
                    pxImage.rows = 9;
                    startCount++;
                }
                else {
                    if (deci == true) {
                        pxImage.dataStore[dataCount] = (float)0.9;
                        trueCount--;
                        deci = false;
                    }
                    else {
                        pxImage.dataStore[dataCount] = 9;
                        trueCount++;
                    }
                }
                break;
        }
    }

    //pxImage.dataStore.resize(trueCount);
}

void game2D::loadAsset()
{
    std::ifstream infile("c:\\heart.pxl", std::ios::hex || std::ios::in);
    if (infile.is_open())
    {
        infile.seekg(0, std::ios::end);
        filesize = (long)infile.tellg();
        infile.seekg(0, std::ios::beg);

        fileContents.resize(filesize);
        tempStore.resize(filesize);

        infile.read((char*)&tempStore[0], filesize);

        infile.close();
    }
    storeSize = 0;

    convertTo();

}

void game2D::game2DRender()
{
    std::vector <float> test;
    if (CDevComplete)
    {
        D2DRenderTarget->BeginDraw();
        D2DRenderTarget->SetTransform(D2D1::Matrix3x2F::Identity());
        D2DRenderTarget->Clear(D2D1::ColorF(D2D1::ColorF::HotPink));
        D2D1_SIZE_F rtSize = D2DRenderTarget->GetSize();

        int width = static_cast<int>(rtSize.width);
        int height = static_cast<int>(rtSize.height);

        loadAsset();

        float locLeft = 100.0f;
        float locTop = 100.0f;
        int pxCount = 2;

        int check4Black = 0;

        float sizeOfPixel = 10.0f;

        float tempLeft = 0.0f;
        float tempTop = 0.0f;

        float f1 = 0.0f;
        float f2 = 0.0f;
        float f3 = 0.0f;


        for (int i = 0; i < pxImage.rows; i++)
        {
            for (int j = 0; j < pxImage.cols; j++)
            {

                D2D1_RECT_F rect1 = D2D1::RectF(
                    locLeft + ((float)j * sizeOfPixel),
                    locTop + ((float)i * sizeOfPixel),
                    locLeft + ((float)j * sizeOfPixel) + sizeOfPixel,
                    locTop + ((float)i * sizeOfPixel) + sizeOfPixel
                    );

                check4Black = pxCount;

                f1 = pxImage.dataStore[check4Black++];
                f2 = pxImage.dataStore[check4Black++];
                f3 = pxImage.dataStore[check4Black++];


                if (f1 == 0.0f && f2 == 0.0f && f3 == 0.0f)
                {
                    D2DRenderTarget->CreateSolidColorBrush(
                        D2D1::ColorF(D2D1::ColorF::Black),
                        &D2DColorBrush
                        );
                    pxCount += 4;
                }
                else
                {
                    D2DRenderTarget->CreateSolidColorBrush(
                        D2D1::ColorF(D2D1::ColorF(pxImage.dataStore[pxCount++], pxImage.dataStore[pxCount++], pxImage.dataStore[pxCount++], pxImage.dataStore[pxCount++])),
                        &D2DColorBrush
                        );
                }
                D2DRenderTarget->FillRectangle(&rect1, D2DColorBrush);
            }
        }

        D2DRenderTarget->EndDraw();
    }
    else
    {
        game2DShutdown();
    }

}

HRESULT game2D::game2DCreateDevice(HWND localHWND)
{
    HRESULT hr;

    if (!D2DRenderTarget)
    {
        RECT rc;
        GetClientRect(localHWND, &rc);

        D2D1_SIZE_U size = D2D1::SizeU(
            rc.right - rc.left,
            rc.bottom - rc.top);

        hr = D2DFactory->CreateHwndRenderTarget(
            D2D1::RenderTargetProperties(),
            D2D1::HwndRenderTargetProperties(localHWND, size),
            &D2DRenderTarget);
        if (SUCCEEDED(hr))
        {
            CDevComplete = true;
        }

    }

    return hr;
}

void game2D::game2DShutdown()
{
    /*
    ID2D1Factory*   D2DFactory;
    ID2D1HwndRenderTarget*  D2DRenderTarget;
    ID2D1SolidColorBrush*   D2DColorBrush;
    ID2D1LinearGradientBrush*   D2DGradientBrush;
    */

    CDevComplete = false;

    if (D2DColorBrush != NULL)
    {
        D2DColorBrush->Release();
        D2DColorBrush = NULL;
    }

    if (D2DRenderTarget != NULL)
    {
        D2DRenderTarget->Release();
        D2DRenderTarget = NULL;
    }

    if (D2DFactory != NULL)
    {
        D2DFactory->Release();
        D2DFactory = NULL;
    }
}

----

These two images show the result:

With a black background: Click Here
With a hot pink background: Click Here

Also, can I just take this moment to complain about the lack of web based guides/tutorials for direct2D? It's damned infuriating.
Anyway, any help I might recieve would be wonderful.

Oh and I forgot to post the image file:

It goes like this,
first digit is the image width,
second digit is height,
the each 4 digit block after that is RGBA
Colons are seperators.

heart.pxl

8,7,
1,1,1,1,
0,0,0,1,
0,0,0,1,
1,1,1,1,
0,0,0,1,
0,0,0,1,
0,0,0,1,
1,1,1,1,

0,0,0,1,
1,1,1,1,
1,0,0,1,
0,0,0,1,
1,0,0,1,
1,0,0,1,
0.5,0,0,1,
0,0,0,1,

0,0,0,1,
1,1,1,1,
1,0,0,1,
1,0,0,1,
1,0,0,1,
1,0,0,1,
0.5,0,0,1,
0,0,0,1,

0,0,0,1,
1,0,0,1,
1,0,0,1,
1,0,0,1,
1,0,0,1,
1,0,0,1,
0.5,0,0,1,
0,0,0,1,

1,1,1,1,
0,0,0,1,
1,0,0,1,
1,0,0,1,
1,0,0,1,
0.5,0,0,1,
0,0,0,1,
1,1,1,1,

1,1,1,1,
1,1,1,1,
0,0,0,1,
0.5,0,0,1,
0.5,0,0,1,
0,0,0,1,
1,1,1,1,
1,1,1,1,

1,1,1,1,
1,1,1,1,
1,1,1,1,
0,0,0,1,
0,0,0,1,
1,1,1,1,
1,1,1,1,
1,1,1,1,
This article has been dead for over six months. Start a new discussion instead.