course/i> is included.
+When and only when the type is CourseIndividual, the attribute course is included.
*person cls="1" stat="1" st="324000" rt="72550" place="1" course=28>
*name id="4">Jordan Griesmer*/name>
diff --git a/code/image.cpp b/code/image.cpp
new file mode 100644
index 0000000..feec954
--- /dev/null
+++ b/code/image.cpp
@@ -0,0 +1,254 @@
+#include "stdafx.h"
+#include "image.h"
+#include "png/png.h"
+#include
+#include
+#include
+#include
+#include "meosexception.h"
+
+FILE _iob[] = { *stdin, *stdout, *stderr };
+
+extern "C" FILE * __cdecl __iob_func(void)
+{
+ return _iob;
+}
+
+namespace {
+
+ struct PngData {
+ vector memory;
+ size_t ptr;
+ PngData() : ptr(0) {}
+
+ size_t read(uint8_t *dst, size_t count);
+ };
+
+ void readDataFromInputStream(png_structp png_ptr, png_bytep outBytes, png_size_t byteCountToRead) {
+ png_voidp io_ptr = png_get_io_ptr(png_ptr);
+ if (io_ptr == NULL)
+ return; // add custom error handling here
+
+ PngData& inputStream = *(PngData*)io_ptr;
+ const size_t bytesRead = inputStream.read((byte*)outBytes, (size_t)byteCountToRead);
+
+ if ((png_size_t)bytesRead != byteCountToRead)
+ return; // add custom error handling here
+ }
+}
+
+size_t PngData::read(uint8_t *dst, size_t count) {
+ count = min(size_t(memory.size() - ptr), count);
+ memcpy(dst, &memory[ptr], count);
+ ptr += count;
+ return count;
+}
+
+// Creates a stream object initialized with the data from an executable resource.
+vector Image::loadResourceToMemory(LPCTSTR lpName, LPCTSTR lpType) {
+ vector result;
+ // find the resource
+ HRSRC hrsrc = FindResource(NULL, lpName, lpType);
+ if (hrsrc == NULL)
+ return result;
+
+ // load the resource
+ DWORD dwResourceSize = SizeofResource(NULL, hrsrc);
+ HGLOBAL hglbImage = LoadResource(NULL, hrsrc);
+ if (hglbImage == NULL)
+ return result;
+
+ // lock the resource, getting a pointer to its data
+ LPVOID pvSourceResourceData = LockResource(hglbImage);
+
+ result.resize(dwResourceSize);
+ memcpy(&result[0], pvSourceResourceData, dwResourceSize);
+
+ return result;
+}
+
+HBITMAP Image::read_png(vector &inData, int &width, int &height, ImageMethod method) {
+ PngData inputStream;
+ inputStream.memory.swap(inData);
+ png_structp png = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
+ if (!png)
+ return nullptr;
+
+ png_infop info = png_create_info_struct(png);
+ if (!info)
+ return nullptr;
+
+ png_set_read_fn(png, &inputStream, readDataFromInputStream);
+
+ png_read_info(png, info);
+
+ width = png_get_image_width(png, info);
+ height = png_get_image_height(png, info);
+ int color_type = png_get_color_type(png, info);
+ int bit_depth = png_get_bit_depth(png, info);
+
+ // Read any color_type into 8bit depth, RGBA format.
+ // See http://www.libpng.org/pub/png/libpng-manual.txt
+
+ if (bit_depth == 16)
+ png_set_strip_16(png);
+
+ if (color_type == PNG_COLOR_TYPE_PALETTE)
+ png_set_palette_to_rgb(png);
+
+ // PNG_COLOR_TYPE_GRAY_ALPHA is always 8 or 16bit depth.
+ if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8)
+ png_set_expand_gray_1_2_4_to_8(png);
+
+ if (png_get_valid(png, info, PNG_INFO_tRNS))
+ png_set_tRNS_to_alpha(png);
+
+ // These color_type don't have an alpha channel then fill it with 0xff.
+ if (color_type == PNG_COLOR_TYPE_RGB ||
+ color_type == PNG_COLOR_TYPE_GRAY ||
+ color_type == PNG_COLOR_TYPE_PALETTE)
+ png_set_filler(png, 0xFF, PNG_FILLER_AFTER);
+
+ if (color_type == PNG_COLOR_TYPE_GRAY ||
+ color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
+ png_set_gray_to_rgb(png);
+
+ png_read_update_info(png, info);
+
+ int rowb = png_get_rowbytes(png, info);
+ vector> data(height, vector(rowb, 0));
+ vector row_pointers_vec(height);
+ for (int y = 0; y < height; y++) {
+ row_pointers_vec[y] = &data[y][0];
+ }
+ png_bytepp row_pointers = &row_pointers_vec[0];
+
+ png_read_image(png, row_pointers);
+
+ // initialize return value
+ HBITMAP hbmp = NULL;
+
+ // prepare structure giving bitmap information (negative height indicates a top-down DIB)
+ BITMAPINFO bminfo;
+ ZeroMemory(&bminfo, sizeof(bminfo));
+ bminfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
+ bminfo.bmiHeader.biWidth = width;
+ bminfo.bmiHeader.biHeight = ((LONG)-height);
+ bminfo.bmiHeader.biPlanes = 1;
+ bminfo.bmiHeader.biBitCount = 32;
+ bminfo.bmiHeader.biCompression = BI_RGB;
+
+ // create a DIB section that can hold the image
+ void * pvImageBits = NULL;
+ HDC hdcScreen = GetDC(NULL);
+ hbmp = CreateDIBSection(hdcScreen, &bminfo, DIB_RGB_COLORS, &pvImageBits, NULL, 0);
+ ReleaseDC(NULL, hdcScreen);
+
+ // extract the image into the HBITMAP
+ const size_t cbStride = width * 4;
+ const size_t cbImage = cbStride * height;
+ byte *dst = static_cast(pvImageBits);
+ for (int y = 0; y < height; y++) {
+ byte *row = dst + cbStride * y;
+ byte *src = row_pointers_vec[y];
+
+ if (method == ImageMethod::MonoAlpha) {
+ for (size_t x = 0; x < cbStride; x += 4) {
+ row[x + 2] = 0;// src[x + 0]; // Red
+ row[x + 1] = 0;// src[x + 1]; // Green
+ row[x + 0] = 16;// src[x + 2]; // Blue
+ row[x + 3] = 255 - src[x + 0];// ((x/100)%8)*31+1;// 255 - src[x + 0]; // Alpha
+
+ if (row[x + 3] == 0) {
+ row[x + 1] = 0;
+ row[x + 2] = 0;
+ row[x + 0] = 0;
+ }
+ }
+ }
+ else if (method == ImageMethod::Default) {
+ for (size_t x = 0; x < cbStride; x += 4) {
+ row[x + 2] = src[x + 0]; // Red
+ row[x + 1] = src[x + 1]; // Green
+ row[x + 0] = src[x + 2]; // Blue
+ row[x + 3] = src[x + 3];
+ }
+ }
+ }
+ return hbmp;
+}
+
+HBITMAP Image::read_png_file(const wstring &filename, int &width, int &height, ImageMethod method) {
+ width = 0;
+ height = 0;
+ PngData inputStream;
+ inputStream.memory;
+
+ ifstream fin;
+ fin.open(filename, ios::binary);
+ fin.seekg(0, ios::end);
+ int p2 = (int)fin.tellg();
+ fin.seekg(0, ios::beg);
+ inputStream.memory.resize(p2);
+ fin.read((char *)&inputStream.memory[0], inputStream.memory.size());
+ fin.close();
+ return read_png(inputStream.memory, width, height, method);
+}
+
+HBITMAP Image::read_png_resource(LPCTSTR lpName, LPCTSTR lpType, int &width, int &height, ImageMethod method) {
+ width = 0;
+ height = 0;
+ PngData inputStream;
+ inputStream.memory = loadResourceToMemory(lpName, lpType);
+ if (inputStream.memory.empty())
+ return nullptr;
+ return read_png(inputStream.memory, width, height, method);
+}
+
+Image::Image()
+{
+}
+
+Image::~Image()
+{
+}
+
+// Loads the PNG containing the splash image into a HBITMAP.
+HBITMAP Image::loadImage(int resource, ImageMethod method) {
+ if (images.count(resource))
+ return images[resource].image;
+
+ int width, height;
+ HBITMAP hbmp = read_png_resource(MAKEINTRESOURCE(resource), _T("PNG"), width, height, method);
+ if (hbmp != 0) {
+ images[resource].image = hbmp;
+ images[resource].width = width;
+ images[resource].height = height;
+ }
+ return hbmp;
+}
+
+int Image::getWidth(int resource) {
+ loadImage(resource, ImageMethod::Default);
+ return images[resource].width;
+}
+
+int Image::getHeight(int resource) {
+ loadImage(resource, ImageMethod::Default);
+ return images[resource].height;
+}
+
+void Image::drawImage(int resource, ImageMethod method, HDC hDC, int x, int y, int width, int height) {
+ HBITMAP bmp = loadImage(resource, method);
+ HDC memdc = CreateCompatibleDC(hDC);
+ SelectObject(memdc, bmp);
+
+ BLENDFUNCTION bf;
+ bf.BlendOp = AC_SRC_OVER;
+ bf.BlendFlags = 0;
+ bf.SourceConstantAlpha =0xFF;
+ bf.AlphaFormat = AC_SRC_ALPHA;
+ AlphaBlend(hDC, x, y, width, height, memdc, 0, 0, width, height, bf);
+
+ DeleteDC(memdc);
+}
diff --git a/code/image.h b/code/image.h
new file mode 100644
index 0000000..490c0b1
--- /dev/null
+++ b/code/image.h
@@ -0,0 +1,41 @@
+#pragma once
+
+#include