RenderD7 0.9.4 (New Stuff, Lot Fixes, Envtools)

This commit is contained in:
2023-03-24 19:46:41 +01:00
parent 7c190e3cfa
commit ae8181a6e5
83 changed files with 49798 additions and 457 deletions
+5
View File
@@ -0,0 +1,5 @@
#pragma once
#include <renderd7/StealConsole.hpp>
#include <renderd7/bmp.hpp>
#include <renderd7/renderd7.hpp>
@@ -0,0 +1,219 @@
#pragma once
#include <string>
#include <vector>
#include <renderd7/bmp.hpp>
#include <renderd7/bmpconverter.hpp>
#include <renderd7/Image.hpp>
#include <renderd7/Screen.hpp>
#include <renderd7/Time.hpp>
#include <renderd7/Fonts/NFontApi.hpp>
namespace RenderD7 {
/// @brief Encoder
enum Encoder {
BITMAP, ///< Encode Data to Bitmap
DIRECT, ///< Encode Direct to Framebuffer(No Decoder Required)
C3D ///< Encode Directly to C3D_Tex (Just an Idea)
};
/// @brief Decoder
enum Decoder {
BITMAP2C3D, ///< Decode and Encode to C3D_Tex (Currently Fastest) (47,4ms)
BITMAP2PNG2C3D ///< Decode Bitmap end Convert to Png, then C3D (Very Slow)
///< (201,4ms)
};
/// @brief BitmapPrinetr Class
class BitmapPrinter {
public:
/// @brief Constructor
/// @param w Widrth
/// @param h Height
BitmapPrinter(int w, int h);
/// @brief Deconstructor
~BitmapPrinter();
/// @brief Dexode Bitmap File
/// @param file path to File
/// @return success ?
bool DecodeFile(std::string file);
/// @brief Set the Decoder
/// @param deccc Decoder
void SetDecoder(Decoder deccc) { decc = deccc; }
/// @brief Draw a Pixel
/// @param x pos x
/// @param y pos y
/// @param b color blue
/// @param g color green
/// @param r color red
/// @param a color alpha
void DrawPixel(int x, int y, u8 b, u8 g, u8 r, u8 a);
/// @brief Draw Rectangle
/// @param x pos x
/// @param y pos y
/// @param w width
/// @param h height
/// @param line_w line width
/// @param b color blue
/// @param g color green
/// @param r color red
/// @param a colr alpha
void DrawRect(int x, int y, int w, int h, u8 line_w, u8 b, u8 g, u8 r, u8 a);
/// @brief Draw a Fillif Rectangle
/// @param x pos x
/// @param y pos y
/// @param w width
/// @param h height
/// @param b color blue
/// @param g color green
/// @param r color red
/// @param a color alpha
void DrawRectFilled(int x, int y, int w, int h, u8 b, u8 g, u8 r, u8 a);
/// @brief Draw Bitmap
/// @param x pos x
/// @param y pos y
/// @param map Bitmap to Print
void DrawBitmap(int x, int y, BMP map);
/// @brief Use Prebuild Bitmap
/// @param map bitmap
void UsePreMap(BMP map);
/// @brief Use Prebuild Printer Setup
/// @param printmap Printer
void UsePrePrintMap(BitmapPrinter printmap);
/// @brief Get Bitmap
/// @return Bitmap
BMP GetBitmap() { return bitmap; }
/// @brief Save to File
/// @param name Name/Path
void SaveBmp(std::string name);
/// @brief Save as Png
/// @param name Name/Path
void SavePng(std::string name);
/// @brief Setup Screen
/// @param target Screen
void CreateScreen(C3D_RenderTarget *target);
/// @brief Draw Directly to Screen With Framerate
/// @param framerate Framerate
/// @return
bool DrawScreenDirectF(int framerate);
/// @brief Draw Directly to Screen
/// @return
bool DrawScreenDirect();
/// @brief Render on Screen by Framerate
/// @param framerate Framerate
void DrawScreenF(int framerate);
/// @brief Draw to Screen
void DrawScreen();
/// @brief Update Image by Framerate
/// @param framerate Framerate
/// @return
bool UpdateScreenF(int framerate);
/// @brief Update Image
/// @return
bool UpdateScreen();
/// @brief Clear by Color
/// @param b color blue
/// @param g color green
/// @param r color red
/// @param a color alpha
void Clear(u8 b = 0, u8 g = 0, u8 r = 0, u8 a = 255);
/// @brief Clear Completly Blank
void ClearBlank();
/// @brief Get Rendered Image
/// @return Image
RenderD7::Image GetImage();
/// Test to Find out The Best Settings for BitmapPrinter
void Benchmark();
/// @brief Setup the Benchmark
/// \param framerate The Fps of the ScreenUpdates
void SetupBenchmark(int framerate);
/// @brief Check if Benchmark is Running
/// @return is running or not
bool IsBenchmarkRunning() { return this->benchmark; }
/// @brief Draw a Dubug Text
/// @param x pos x
/// @param y pos y
/// @param t_size Size of the Text
/// @param color Color of the Text
/// @param text String of the Text
void DrawDebugText(int x, int y, int t_size, u32 color, std::string text);
/// @brief Draw a Text width NFontApi (TTF)
/// @param x pos x
/// @param y pos y
/// @param t_size size of the Text
/// @param color Color of The Text
/// @param text String of The Text
/// @param font TTF Font
void DrawText(int x, int y, float t_size, u32 color, std::string text,
RenderD7::NFontApi font);
private:
// funcs
/// @brief Decode 2 RenderD7::Image
/// @param deccc Decoder
/// @return
bool Decode(Decoder deccc);
/// @brief Draw Char Func
/// @param posX pos x
/// @param posY pos y
/// @param t_size size
/// @param color color
/// @param character char
void DrawDebugChar(u32 posX, u32 posY, int t_size, u32 color, char character);
/// @brief NFont Draw Char
/// @param posX pos x
/// @param posY pos y
/// @param t_size size
/// @param color color
/// @param character char
/// @param font ttf
void DrawChar(int posX, int posY, float t_size, u32 color, char character,
RenderD7::NFontApi font);
// parameter
int frame = 0;
RenderD7::Image renderframe;
bool isscreen = false;
C3D_RenderTarget *targetr;
BMP bitmap = BMP(
20, 20,
true); // Need to Set e Predefined Bitmap. If not the System will Crash.
BMP blank = BMP(
20, 20,
true); // Need to Set e Predefined Bitmap. If not the System will Crash.
///////////////////////////////////////////////////////////////////////////////////////////////////
// Benchmark Stuff;
int testfpsd;
bool benchmark = false;
bool setupbenchmark;
float frametime = 0;
uint64_t lastTime = 0;
float dtt = 0.f;
float dtt2 = 0.f;
float dtt3 = 0.f;
float timer = 0;
float mhdtt = 0;
float mdtt2;
float mdtt3;
float fpsClock = 0.f;
int frameCounter = 0, fps = 0;
std::vector<float> hdttt;
std::vector<float> hdttt2;
std::vector<float> hdttt3;
std::vector<int> fpscountc;
int renderedframes = 0;
int testfps = 60;
Encoder encc = Encoder::BITMAP;
Decoder decc = Decoder::BITMAP2C3D;
////////////////////////////////////////////////////////////////////////////////////////////////
};
} // namespace RenderD7
+50
View File
@@ -0,0 +1,50 @@
#pragma once
#include <cstring>
#include <functional>
#include <memory>
#include <regex>
#include <sstream>
#include <string>
#include <unistd.h>
#define UNPACK_RGBA(col) (uint8_t)(col >> 24), (col >> 16), (col >> 8), (col)
#define UNPACK_BGRA(col) (uint8_t)(col >> 8), (col >> 16), (col >> 24), (col)
namespace RenderD7 {
namespace Color {
/// @brief RGBA Struct
struct rgba {
/// @brief rgba Colors
uint8_t r, g, b, a;
};
/// @brief RGBA Class
class RGBA {
public:
/// @brief Construct
/// @param r
/// @param g
/// @param b
/// @param a
RGBA(uint8_t r, uint8_t g, uint8_t b, uint8_t a)
: m_r(r), m_g(g), m_b(b), m_a(a) {}
/// @brief Get as Uint32
/// @return color
uint32_t toRGBA() const {
return (m_r << 24) | (m_g << 16) | (m_b << 8) | m_a;
}
uint8_t m_r, m_g, m_b, m_a;
};
/// @brief Convert RGB to Hex
/// @param r
/// @param g
/// @param b
/// @return Hex-String
std::string RGB2Hex(int r, int g, int b);
/// @brief Hex to U32
/// @param color
/// @param a
/// @return Color32
uint32_t Hex(const std::string &color, uint8_t a = 255);
} // namespace Color
} // namespace RenderD7
+111
View File
@@ -0,0 +1,111 @@
#pragma once
#include <3ds.h>
#include <citro2d.h>
#include <citro3d.h>
#include <string>
namespace RenderD7 {
namespace Draw {
/// @brief Draw Rectangle
/// @param x Pos X
/// @param y Pos Y
/// @param w Width
/// @param h Height
/// @param color Color
/// @return success ?
bool Rect(float x, float y, float w, float h, u32 color);
/// @brief Draw a not filled Rectangle
/// @param p1x Pos X
/// @param p1y Pos Y
/// @param w Width
/// @param h Height
/// @param color Color
/// @param scale Scale
/// @return success ?
bool NFRect(float p1x, float p1y, float w, float h, u32 color, float scale = 1);
/// @brief Draw A Pixel
/// @param x Pos X
/// @param y Pos Y
/// @param color Color
/// @return success ?
bool Px(float x, float y, u32 color);
/// @brief Draw a Centered Text
/// @param x Pos X
/// @param y Pos Y
/// @param size Scale of the Text
/// @param color Color of The Text
/// @param Text Striing to Display
/// @param maxWidth Width to Calculate Centered Pos
/// @param maxHeight Height to Calculate Centered Pos
/// @param fnt Custom Font
void TextCentered(float x, float y, float size, u32 color, std::string Text,
int maxWidth = 0, int maxHeight = 0, C2D_Font fnt = nullptr);
/// @brief Draw a Text
/// @param x Pos X
/// @param y Pos Y
/// @param size Scale of the Text
/// @param color Color of The Text
/// @param Text Striing to Display
/// @param maxWidth Width to Calculate Centered Pos
/// @param maxHeight Height to Calculate Centered Pos
/// @param fnt Custom Font
void Text(float x, float y, float size, u32 color, std::string Text,
int maxWidth = 0, int maxHeight = 0, C2D_Font fnt = nullptr);
/// @brief Draw a Text Set to the Right
/// @param x Pos X
/// @param y Pos Y
/// @param size Scale of the Text
/// @param color Color of The Text
/// @param Text Striing to Display
/// @param maxWidth Width to Calculate Centered Pos
/// @param maxHeight Height to Calculate Centered Pos
/// @param fnt Custom Font
void TextRight(float x, float y, float size, u32 color, std::string Text,
int maxWidth = 0, int maxHeight = 0, C2D_Font fnt = nullptr);
/// @brief Get Width of Text
/// @param size Size of the Text
/// @param Text String of The text
/// @param fnt Custom Font
/// @return The Size
float GetTextWidth(float size, std::string Text, C2D_Font fnt = nullptr);
/// @brief Get Text Size
/// @param size Size of The Text
/// @param width Width of the Text
/// @param height Height of The Text
/// @param Text String of Text
/// @param fnt Custom Font
void GetTextSize(float size, float *width, float *height, std::string Text,
C2D_Font fnt = nullptr);
/// @brief Get Height of the Text
/// @param size Size of the Text
/// @param Text String of the Text
/// @param fnt Custom Font
/// @return The Height
float GetTextHeight(float size, std::string Text, C2D_Font fnt = nullptr);
/// @brief Load A .bcfnt
/// @param fnt Output Font
/// @param Path path of The File
/// @return Result Code
Result LoadFont(C2D_Font &fnt, const char *Path = "");
/// @brief Unload a Font
/// @param fnt Font to Unload
/// @return Result Code
Result UnloadFont(C2D_Font &fnt);
/// @brief Draw a Circle
/// @param x Pos X
/// @param y Pos Y
/// @param radius Radius of the Circle
/// @param color Color of the circle
/// @return success ?
bool Circle(float x, float y, float radius, u32 color);
/// @brief Draw A Citro2D Image
/// @param img Image to Draw
/// @param x Pos X
/// @param y Pos Y
/// @param scaleX Scale of X-Axis
/// @param scaleY Scale of Y-Axis
/// @return success ?
bool Image(C2D_Image img, float x, float y, float scaleX = 1.0f,
float scaleY = 1.0f);
} // namespace Draw
} // namespace RenderD7
@@ -0,0 +1,23 @@
// FileSystem based on libphyfs based on
// https://github.com/TurtleP/3ds-examples/blob/fs/physfs/fs/physfs/include/filesystem.h
#pragma once
#include <string>
#include <vector>
namespace RenderD7 {
namespace FileSystem {
/// @brief A Directory Entry
struct Entry {
/// @brief Patf of The Entry
std::string path;
/// @brief Name of The Entry
std::string name;
/// @brief Directory or File
bool dir = false;
};
/// @brief Gets All Entrys of A Directory into a Vector
/// @param path The Path of the Directory
/// @return The Vector of found Entrys
std::vector<RenderD7::FileSystem::Entry> GetDirContent(std::string path);
} // namespace FileSystem
} // namespace RenderD7
@@ -0,0 +1,142 @@
#pragma once
#include <bitset>
#include <iostream>
#include <string>
#include <vector>
#include <renderd7/external/stb_truetype.h>
#define MAXUNICODE 0x10FFFF
namespace RenderD7 {
inline int utf8_decode(const char *o) {
static const unsigned int limits[] = {0xFF, 0x7F, 0x7FF, 0xFFFF};
const unsigned char *s = (const unsigned char *)o;
unsigned int c = s[0];
unsigned int res = 0; /* final result */
if (c < 0x80) /* ascii? */
res = c;
else {
int count = 0; /* to count number of continuation bytes */
while (c & 0x40) { /* still have continuation bytes? */
int cc = s[++count]; /* read next byte */
if ((cc & 0xC0) != 0x80) /* not a continuation byte? */
return -1; /* invalid byte sequence */
res = (res << 6) | (cc & 0x3F); /* add lower 6 bits from cont. byte */
c <<= 1; /* to test next bit */
}
res |= ((c & 0x7F) << (count * 5)); /* add first byte */
if (count > 3 || res > MAXUNICODE || res <= limits[count])
return -1; /* invalid byte sequence */
s += count; /* skip continuation bytes read */
}
return res;
}
inline std::string IntToUtf8(int convertval) {
// We only care about plane 1 right now,
// but know that we have other options (0x10FFFF)
// Technically UTF-8 is "limited" to 4 bytes, so it's not
// Like it matters much anyways these days
if (convertval == 0)
return " ";
if ((convertval <= 0x7F) && (convertval > 0x00)) {
std::string out(".");
std::bitset<8> x(convertval);
unsigned long l = x.to_ulong();
unsigned char c = static_cast<unsigned char>(l);
out[0] = c;
return out;
} else if ((convertval >= 0x80) && (convertval <= 0x07FF)) {
std::string out("..");
int firstShift = (convertval >> 0x06) ^ 0xC0;
int secondShift = ((convertval ^ 0xFFC0) | 0x80) & ~0x40;
std::bitset<8> first(firstShift);
std::bitset<8> last(secondShift);
unsigned long l = first.to_ulong();
unsigned char c = static_cast<unsigned char>(l);
out[0] = c;
unsigned long ltwo = last.to_ulong();
unsigned char ctwo = static_cast<unsigned char>(ltwo);
out[1] = ctwo;
return out;
} else if ((convertval >= 0x0800) && (convertval <= 0xFFFF)) {
std::string out("...");
int firstShift = ((convertval ^ 0xFC0FFF) >> 0x0C) | 0xE0;
int secondShift = (((convertval ^ 0xFFF03F) >> 0x06) | 0x80) & ~0x40;
int thirdShift = ((convertval ^ 0xFFFC0) | 0x80) & ~0x40;
std::bitset<8> first(firstShift);
std::bitset<8> second(secondShift);
std::bitset<8> third(thirdShift);
unsigned long lone = first.to_ulong();
unsigned char cone = static_cast<unsigned char>(lone);
out[0] = cone;
unsigned long ltwo = second.to_ulong();
unsigned char ctwo = static_cast<unsigned char>(ltwo);
out[1] = ctwo;
unsigned long lthree = third.to_ulong();
unsigned char cthree = static_cast<unsigned char>(lthree);
out[2] = cthree;
return out;
} else {
return " ";
}
}
#define I2U82I(val) RenderD7::utf8_decode(RenderD7::IntToUtf8(val).c_str())
class NFontApi {
public:
NFontApi();
~NFontApi();
void LoadTTF(std::string path);
unsigned char *GetGlyphBitmap(char glyph);
std::string GetStatus() { return status; }
float GetScale() { return scale; }
int GetGlyphWidth(char glyph);
int GetGlyphHeight(char glyph);
int GetLineHeight() { return l_h; }
int GetBaseHeight() { return height; }
private:
std::string status;
int height;
float scale;
int b_w;
int b_h;
int l_h;
int w;
int h;
int x0, y0, x1, y1;
int ascent, baseline, decent, linegap;
int linespace;
stbtt_fontinfo font;
};
} // namespace RenderD7
@@ -0,0 +1,52 @@
#pragma once
// Base includes
#include <functional>
#include <map>
#include <memory>
#include <string>
#include <vector>
// 3ds does not support std::chrono
#include <3ds.h>
/// @brief 3ds System Ticks per milli second
#define TICKS_PER_MSEC 268111.856
#define f2s(x_) #x_
#define scomb(x1, x2) std::string(x1 + x2)
namespace RenderD7 {
namespace Ftrace {
/// @brief Result of FTrace
struct FTRes {
std::string group; ///< Group of the Trace
std::string func_name; ///< Function Name
uint64_t time_start; ///< when started
uint64_t time_end; ///< when stopped
float time_of; ///< stop - start (how long)
};
/// @brief Map of Traces
extern std::map<std::string, RenderD7::Ftrace::FTRes> rd7_traces;
/// @brief Set a Start TracePoint
/// @param group Set a Group Name
/// @param func_name Set a Function Name
inline void Beg(std::string group, std::string func_name) {
std::string trace_id = scomb(group, func_name);
rd7_traces[trace_id].group = group;
rd7_traces[trace_id].func_name = func_name;
rd7_traces[trace_id].time_start = svcGetSystemTick();
}
/// @brief Set an End TracePoint
/// @param group Set a Group Name
/// @param func_name Set a Function Name
inline void End(std::string group, std::string func_name) {
std::string trace_id = scomb(group, func_name);
rd7_traces[trace_id].time_end = svcGetSystemTick();
rd7_traces[trace_id].time_of = static_cast<float>(
rd7_traces[trace_id].time_end / (float)TICKS_PER_MSEC -
rd7_traces[trace_id].time_start / (float)TICKS_PER_MSEC);
}
} // namespace Ftrace
} // namespace RenderD7
+23
View File
@@ -0,0 +1,23 @@
#pragma once
namespace RenderD7 {
namespace Hardware {
/// @brief Initialisize required Services
void Initialisize();
/// @brief Check if Headphones are Plugged in
/// @return true if headphones plugged in
bool IsHeadphones();
/// @brief Check if the 3ds Is Charging
/// @return true if System gets Charged
bool IsCharging();
/// @brief Check the Battery Percentage
/// @return Persentage as float
float GetBatteryPercentage();
/// @brief Get current State of 3d Slider
/// @return current 3dslider poition
float Get3dSliderLevel();
/// @brief Get Current state of Sound Slider
/// @return current SoundSlider state
float GetSoundSliderLevel();
} // namespace Hardware
} // namespace RenderD7
+50
View File
@@ -0,0 +1,50 @@
#pragma once
#include <citro2d.h>
#include <citro3d.h>
#include <memory>
#include <renderd7/Sheet.hpp>
#include <renderd7/bmp.hpp>
#include <renderd7/bmpconverter.hpp>
#include <cassert>
#include <cstring>
#include <renderd7/Color.hpp>
#include <renderd7/external/lodepng.h>
namespace RenderD7 {
/// Image Class
class Image {
public:
/// @brief Constructor
Image() {}
/// @brief Deconstructor
~Image();
/// @brief Unload The Image
void Unload();
/// Load Image from Png
/// \param path path to png file
void LoadPng(const std::string path);
/// Load the Image from buffer
/// \param buffer the frame buffer
void LoadPFromBuffer(const std::vector<u8> &buffer);
void LoadFromBitmap(BMP bitmap);
void LoadJpg(std::string path);
void LoadPixels(int w, int h, int bpp, void *buffer);
/// Draw the Image directly
/// \param x The x position
/// \param y the y position
/// \param scaleX x scale from 0.0 to 1.0
/// \param scaleY y scale from 0.0 to 1.0
bool Draw(float x, float y, float scaleX = 1.0f, float scaleY = 1.0f);
/// \brief Get The Image
/// \return C2D_Image
C2D_Image Get() { return this->img; }
void FromSheet(RenderD7::Sheet sheet, size_t index);
/// \param img this is the C2D_Image
C2D_Image img;
/// \param loadet whether the image is loadet or not
bool loadet = false;
};
} // namespace RenderD7
+25
View File
@@ -0,0 +1,25 @@
#pragma once
#include <cstdint>
#include <memory>
namespace RenderD7 {
namespace Memory {
/// @brief Metriks struct For the Internal Tracker
struct memory_metrics {
uint32_t t_TotalAllocated = 0; ///< Total Allocated Memory
uint32_t t_TotalFreed = 0; ///< Total Deleted Memory
/// @brief Gets the Currently Allocated Memory
uint32_t t_CurrentlyAllocated() { return t_TotalAllocated - t_TotalFreed; }
};
/// @brief Get Total Allocated Memory
/// @return Total Allocated Memory
size_t GetTotalAllocated();
/// @brief Get Total Deleted Memory
/// @return Total Deleted Memory
size_t GetTotalFreed();
/// @brief Get Current Allocated Memory
/// @return Current Allocated Memory
size_t GetCurrent();
} // namespace Memory
} // namespace RenderD7
+64
View File
@@ -0,0 +1,64 @@
#pragma once
#include <renderd7/Ovl.hpp>
namespace RenderD7 {
class Ovl_Ftrace : public RenderD7::Ovl {
/// @brief Constructor
Ovl_Ftrace();
/// @brief Override for Draw
void Draw(void) const override;
/// @brief Override for Logic
void Logic() override;
private:
};
class Ovl_UiBattery : public RenderD7::Ovl {
/// @brief Constructor
/// @param percentage Percentage
Ovl_UiBattery(float *percentage);
/// @brief Override for Draw
void Draw(void) const override;
/// @brief Override for Logic
void Logic() override;
private:
float *_pct_addr = 0;
};
class Ovl_UiSound : public RenderD7::Ovl {
/// @brief Constructor
/// @param percentage Percentage
Ovl_UiSound(float *percentage);
/// @brief Override for Draw
void Draw(void) const override;
/// @brief Override for Logic
void Logic() override;
private:
float *_pct_addr = 0;
};
class Ovl_Ui3d : public RenderD7::Ovl {
/// @brief Constructor
/// @param percentage Percentage
Ovl_Ui3d(float *percentage);
/// @brief Override for Draw
void Draw(void) const override;
/// @brief Override for Logic
void Logic() override;
private:
float *_pct_addr = 0;
};
class Ovl_UiWifi : public RenderD7::Ovl {
/// @brief Constructor
/// @param level strengh level
Ovl_UiWifi(uint8_t *level);
/// @brief Override for Draw
void Draw(void) const override;
/// @brief Override for Logic
void Logic() override;
private:
uint8_t *_pct_addr = 0;
};
} // namespace RenderD7
+30
View File
@@ -0,0 +1,30 @@
#pragma once
#include <memory>
namespace RenderD7 {
/// @brief The Overlay Class (Used for Toasts for example)
class Ovl {
public:
/// @brief Deconstructor
virtual ~Ovl() {}
/// @brief Function Called to Draw this
virtual void Draw() const = 0;
/// @brief Logic of the Overlay
virtual void Logic() = 0;
/// @brief Should the overlay be killed
/// @return Killed or Not
inline bool IsKilled() { return this->iskilled; }
/// @brief Kill The Overlay
inline void Kill() { iskilled = true; }
private:
/// @param iskilled For IsKilled();
bool iskilled = false;
};
/// @brief Add an Overlay to the Screen
/// @param scene Overlay to push to Screen
void AddOvl(std::unique_ptr<RenderD7::Ovl> scene);
/// @brief Add an Overlay to the Toast Stack
/// @param scene Overlay to push to Toast Stack
void AddToast(std::unique_ptr<RenderD7::Ovl> scene);
} // namespace RenderD7
@@ -0,0 +1,51 @@
#pragma once
#include <3ds.h>
#include <string>
namespace RenderD7 {
/// @brief Decoder for 3ds Result Codes
class ResultDecoder {
public:
/// @brief Constructor
ResultDecoder() {}
/// @brief Deconstructor
~ResultDecoder() {}
/// @brief Load a Result into Decoder
/// @param rescode Result Code
void Load(Result rescode);
/// @brief Load A Hex Converted Code into Decoder
/// @param rescode Result-Hex Code
void Load(std::string rescode);
/// @brief Get Hex Code
/// @return Hex-Code
std::string GetCode();
/// @brief Get Level Name
/// @return Level Name
std::string GetLevel();
/// @brief Get Level Value
/// @return Level Value
int GetLevelInt();
/// @brief Get The Mosule Name
/// @return Module Name
std::string GetModule();
/// @brief Get The Module Value
/// @return Module Value
int GetModuleInt();
/// @brief Get The Description
/// @return Description
std::string GetDescription();
/// @brief Get The Description Valur
/// @return Description Value
int GetDescriptionInt();
/// @brief Get the Summary
/// @return Summary
std::string GetSummary();
/// @brief Get the Summary Value
/// @return Summary Value
int GetSummaryInt();
private:
/// @param m_rescode Result code
Result m_rescode;
};
} // namespace RenderD7
+16
View File
@@ -0,0 +1,16 @@
#pragma once
#include <citro2d.h>
#include <citro3d.h>
/// \param Top Tob-Screen Target
extern C3D_RenderTarget *Top;
/// \param TopRight Top-Right-Screen Target (Never atually used)
extern C3D_RenderTarget *TopRight;
/// \param Bottom Bottom-Screen Target
extern C3D_RenderTarget *Bottom;
namespace RenderD7 {
/// @brief Begin Drawing On Specific Screen
/// @param target The Screen Target (Top, Bottom or TopTight)
void OnScreen(C3D_RenderTarget *target);
} // namespace RenderD7
+60
View File
@@ -0,0 +1,60 @@
#pragma once
#include <cstdint>
#include <functional>
#include <string>
#include <vector>
#include <3ds.h>
namespace RenderD7 {
namespace Init {
void Security();
}
class Security {
public:
/// @brief Security Levels
enum Level {
NONE, ///< Do Completly Nothing (excludes FrameEnd Security)
FULL, ///< Display Every Reports even Success
ERRORS, ///< Display Only Errors
WARNINGS, ///< Display Errors and Warnings
LOG, ///< Log Every Error with Detailed Information
};
Security();
~Security();
/// @brief Report an Output (For SafeTraceInit)
/// @param addr Adress of Pointer
/// @param result_ptr Pointer to the result
void Report(uint32_t addr, void *result_ptr);
/// @brief Set the Security Level
/// @param level Level to use
void SetLevel(Level level);
/// @brief Get Current Security Level
/// @return Security Level
Level GetLevel();
/// @brief Call a Function at Program Crash/Exit
/// @param exit_func Function to Call
void SafeExit(void (*exit_func)());
/// @brief SaveInit a Function and define a Exit Func
/// @param init_func Init Function
/// @param exit_func Exit Function
void SafeInit(void (*init_func)(), void (*exit_func)());
/// @brief SaveInit a Function and define a Exit Func
/// @param init_func Init Function
/// @param exit_func Exit Function
void SafeInit(Result (*init_func)(), void (*exit_func)());
/// @brief SaveInit a Function and define a Exit Func
/// @param init_func Init Function
/// @param exit_func Exit Function
void SafeInit(void (*init_func)(), Result (*exit_func)());
/// @brief SaveInit a Function and define a Exit Func
/// @param init_func Init Function
/// @param exit_func Exit Function
void SafeInit(Result (*init_func)(), Result (*exit_func)());
};
} // namespace RenderD7
/// @brief RenderD7 Security Object
extern RenderD7::Security *rd7_security;
+22
View File
@@ -0,0 +1,22 @@
#pragma once
#include <citro2d.h>
#include <citro3d.h>
namespace RenderD7 {
/// @brief SpriteSheet Class
class Sheet {
public:
/// @brief Constructor
Sheet();
/// @brief Deconstructor
~Sheet();
/// @brief Load A Spritesheet File
/// @param path Path to the t3x
/// @return Result Code
Result Load(const char *path);
/// @brief Unload the Sheet
void Free();
/// \param spritesheet The Sheet
C2D_SpriteSheet spritesheet;
};
} // namespace RenderD7
+64
View File
@@ -0,0 +1,64 @@
#pragma once
#include <citro2d.h>
#include <citro3d.h>
#include <renderd7/Image.hpp>
#include <renderd7/Sheet.hpp>
namespace RenderD7 {
/// @brief Sprite Class
class Sprite {
public:
/// \brief Construct Sprite
Sprite();
/// \brief Deconstruct Sprite
~Sprite();
/// \brief Load a Sprite From SpriteSheet
/// \param sheet the Sheet to load from.(RenderD7::Sheet)
/// \param index the number of the Sprite in the Sheet
void FromSheet(RenderD7::Sheet *sheet, size_t index);
/// \brief Load a Sprite From SpriteSheet
/// \param img the Image to load from.(RenderD7::Image)
void FromImage(RenderD7::Image *img);
/// @brief Draw the Sprite
/// @return success ?
bool Draw();
/// @brief Set the Center Position
/// @param x X Pos
/// @param y Y Pos
void SetCenter(float x, float y);
/// @brief Set the Sprite's Position
/// @param x X Pos
/// @param y Y Pos
void SetPos(float x, float y);
/// @brief Set The Sprite's Scale
/// @param x Scale on X-Axis
/// @param y Scale on Y-Axis
void SetScale(float x, float y);
/// @brief Set the Sprite's Rotation
/// @param rotation ratation
void SetRotation(float rotation);
/// @brief Rotate the Sprite
/// @param speed Speed to Rotate
void Rotate(float speed);
/// @brief Get Tje Sprite's Width
/// @return Width
float getWidth();
/// @brief Get the Sprite's Height
/// @return Height
float getHeight();
/// @brief Get The Sprite's X Position
/// @return X Position
float getPosX();
/// @brief Get the Sprite's Y Position
/// @return Y Position
float getPosY();
private:
/// @param tint ImageTint (unused)
C2D_ImageTint tint;
/// @param sprite The Sprite
C2D_Sprite sprite;
};
} // namespace RenderD7
@@ -0,0 +1,41 @@
#pragma once
#include <renderd7/Sheet.hpp>
#include <renderd7/Sprite.hpp>
#include <citro2d.h>
#include <citro3d.h>
namespace RenderD7 {
/// @brief SpriteSheetAnimation Class
class SpriteSheetAnimation : public RenderD7::Sprite {
public:
/// @brief Constructor
SpriteSheetAnimation();
/// @brief Deconstructor
~SpriteSheetAnimation();
/// @brief Setup an Animation
/// @param sheet Input Spritesheet
/// @param imagecount Count of Images
/// @param startimage Where to Start the Loop
/// @param frame_begin Current Time (Should be 0)
/// @param frame_finish Time Length
void Setup(RenderD7::Sheet *sheet, size_t imagecount, size_t startimage,
float frame_begin, float frame_finish);
/// @brief Play the Animation
/// @param timespeed Speed of the animation
void Play(float timespeed);
private:
/// @param images Count of Images
size_t images;
/// @param imgs Another Count of images ???
size_t imgs = 0;
/// @param D_totaltime Current Time
float D_totaltime;
/// @param sheet The Sheet of Images
RenderD7::Sheet *sheet;
/// @param time Total Time from frame_finish
float time;
};
} // namespace RenderD7
@@ -0,0 +1,21 @@
#pragma once
#include <sstream>
#include <string>
namespace RenderD7 {
/// @brief StealConsole Class
class StealConsole {
public:
/// @brief Constructor
StealConsole();
/// @brief Deconstructor
~StealConsole();
/// @brief The Stolen Stdout
/// @return Stdout as string
std::string GetStdout();
private:
/// @param stolen_stdout Stolen Stdout
std::stringstream stolen_stdout;
};
} // namespace RenderD7
+13
View File
@@ -0,0 +1,13 @@
#pragma once
#include <3ds.h>
#include <vector>
namespace RenderD7 {
namespace Tasks {
/// @brief Push A Task
/// @param entrypoint Function of Your Task
void create(ThreadFunc entrypoint);
/// @brief Destroy all Tasks
void destroy(void);
} // namespace Tasks
} // namespace RenderD7
+13
View File
@@ -0,0 +1,13 @@
#pragma once
#include <string>
namespace RenderD7 {
/// @brief Format a String
/// @param fmt_str Format To
/// @param ... Additional Args
/// @return Formatted String
std::string FormatString(std::string fmt_str, ...);
/// @brief Get Current Time as String
/// @return Time-String
std::string GetTimeStr(void);
} // namespace RenderD7
+30
View File
@@ -0,0 +1,30 @@
#pragma once
#include <renderd7/BitmapPrinter.hpp>
#include <renderd7/Color.hpp>
#include <renderd7/Image.hpp>
#include <renderd7/Ovl.hpp>
#include <renderd7/Screen.hpp>
namespace RenderD7 {
/// @brief Toast Class
class Toast : public RenderD7::Ovl {
public:
/// @brief Constructor
/// @param head Displayed String in Head
/// @param msg Displayed String in Message Box
Toast(std::string head, std::string msg);
/// @brief Override for Draw
void Draw(void) const override;
/// @brief Override for Logic
void Logic() override;
private:
/// @param head The Header Text
/// @param nsg The Message-Box Text
std::string head, msg;
/// @param msgposy Position Y of The Toast
int msgposy = 240;
/// @param delay Delay of the Toast
int delay = 0;
};
} // namespace RenderD7
@@ -0,0 +1,5 @@
#pragma once
#include <cstddef>
extern unsigned char battery_icons[];
extern size_t battery_icons_size;
+707
View File
@@ -0,0 +1,707 @@
#pragma once
#include <fstream>
#include <iostream>
#include <iterator>
#include <sstream>
#include <stdexcept>
#include <vector>
using namespace std;
#pragma pack(push, 1)
struct BMPFileHeader {
uint16_t file_type{0x4D42}; // File type always BM which is 0x4D42 (stored as
// hex uint16_t in little endian)
uint32_t file_size{0}; // Size of the file (in bytes)
uint16_t reserved1{0}; // Reserved, always 0
uint16_t reserved2{0}; // Reserved, always 0
uint32_t offset_data{
0}; // Start position of pixel data (bytes from the beginning of the file)
};
struct BMPInfoHeader {
uint32_t size{0}; // Size of this header (in bytes)
int32_t width{0}; // width of bitmap in pixels
int32_t height{
0}; // height of bitmap in pixels
// (if positive, bottom-up, with origin in lower left corner)
// (if negative, top-down, with origin in upper left corner)
uint16_t planes{1}; // No. of planes for the target device, this is always 1
uint16_t bit_count{0}; // No. of bits per pixel
uint32_t compression{0}; // 0 or 3 - uncompressed. THIS PROGRAM CONSIDERS ONLY
// UNCOMPRESSED BMP images
uint32_t size_image{0}; // 0 - for uncompressed images
int32_t x_pixels_per_meter{0};
int32_t y_pixels_per_meter{0};
uint32_t colors_used{0}; // No. color indexes in the color table. Use 0 for
// the max number of colors allowed by bit_count
uint32_t colors_important{0}; // No. of colors used for displaying the bitmap.
// If 0 all colors are required
};
struct BMPColorHeader {
uint32_t red_mask{0x00ff0000}; // Bit mask for the red channel
uint32_t green_mask{0x0000ff00}; // Bit mask for the green channel
uint32_t blue_mask{0x000000ff}; // Bit mask for the blue channel
uint32_t alpha_mask{0xff000000}; // Bit mask for the alpha channel
uint32_t color_space_type{0x73524742}; // Default "sRGB" (0x73524742)
uint32_t unused[16]{0}; // Unused data for sRGB color space
};
#pragma pack(pop)
class BMP {
public:
BMPFileHeader file_header;
BMPInfoHeader bmp_info_header;
BMPColorHeader bmp_color_header;
std::vector<uint8_t> data;
BMP(const char *fname) { read(fname); }
int read(const char *fname) {
std::ifstream inp{fname, std::ios_base::binary};
if (inp) {
inp.read((char *)&file_header, sizeof(file_header));
if (file_header.file_type != 0x4D42) {
return 50;
// throw std::runtime_error("Error! Unrecognized file format.");
}
inp.read((char *)&bmp_info_header, sizeof(bmp_info_header));
// The BMPColorHeader is used only for transparent images
if (bmp_info_header.bit_count == 32) {
// Check if the file has bit mask color information
if (bmp_info_header.size >=
(sizeof(BMPInfoHeader) + sizeof(BMPColorHeader))) {
inp.read((char *)&bmp_color_header, sizeof(bmp_color_header));
// Check if the pixel data is stored as BGRA and if the color space
// type is sRGB
check_color_header(bmp_color_header);
} else {
// std::cerr << "Error! The file \"" << fname << "\" does not seem to
// contain bit mask information\n"; return 51;//throw
// std::runtime_error("Error! Unrecognized file format.");
}
}
// Jump to the pixel data location
inp.seekg(file_header.offset_data, inp.beg);
// Adjust the header fields for output.
// Some editors will put extra info in the image file, we only save the
// headers and the data.
if (bmp_info_header.bit_count == 32) {
bmp_info_header.size = sizeof(BMPInfoHeader) + sizeof(BMPColorHeader);
file_header.offset_data = sizeof(BMPFileHeader) +
sizeof(BMPInfoHeader) +
sizeof(BMPColorHeader);
} else {
bmp_info_header.size = sizeof(BMPInfoHeader);
file_header.offset_data = sizeof(BMPFileHeader) + sizeof(BMPInfoHeader);
}
file_header.file_size = file_header.offset_data;
if (bmp_info_header.height < 0) {
return 52; // throw std::runtime_error("The program can treat only BMP
// images with the origin in the bottom left corner!");
}
data.resize(bmp_info_header.width * bmp_info_header.height *
bmp_info_header.bit_count / 8);
// Here we check if we need to take into account row padding
if (bmp_info_header.width % 4 == 0) {
inp.read((char *)data.data(), data.size());
file_header.file_size += static_cast<uint32_t>(data.size());
} else {
row_stride = bmp_info_header.width * bmp_info_header.bit_count / 8;
uint32_t new_stride = make_stride_aligned(4);
std::vector<uint8_t> padding_row(new_stride - row_stride);
for (int y = 0; y < bmp_info_header.height; ++y) {
inp.read((char *)(data.data() + row_stride * y), row_stride);
inp.read((char *)padding_row.data(), padding_row.size());
}
file_header.file_size +=
static_cast<uint32_t>(data.size()) +
bmp_info_header.height * static_cast<uint32_t>(padding_row.size());
}
} else {
return 53; // throw std::runtime_error("Unable to open the input image
// file "+std::string(fname));
}
return 0;
}
int read_mem(std::vector<unsigned char> buffer) {
std::stringstream inp;
std::copy(buffer.begin(), buffer.end(),
std::ostream_iterator<unsigned char>(inp, "\n"));
std::cout << buffer.size() << std::endl;
if (inp) {
inp.read((char *)&file_header, sizeof(file_header));
if (file_header.file_type != 0x4D42) {
return 50;
// throw std::runtime_error("Error! Unrecognized file format. Header " +
// std::to_string(file_header.file_type));
}
inp.read((char *)&bmp_info_header, sizeof(bmp_info_header));
// The BMPColorHeader is used only for transparent images
if (bmp_info_header.bit_count == 32) {
// Check if the file has bit mask color information
if (bmp_info_header.size >=
(sizeof(BMPInfoHeader) + sizeof(BMPColorHeader))) {
inp.read((char *)&bmp_color_header, sizeof(bmp_color_header));
// Check if the pixel data is stored as BGRA and if the color space
// type is sRGB
check_color_header(bmp_color_header);
} else {
// std::cerr << "Error! The file \"" << fname << "\" does not seem to
// contain bit mask information\n";
return 51;
// throw std::runtime_error("Error! Unrecognized file format. Size");
}
}
// Jump to the pixel data location
inp.seekg(file_header.offset_data, inp.beg);
// Adjust the header fields for output.
// Some editors will put extra info in the image file, we only save the
// headers and the data.
if (bmp_info_header.bit_count == 32) {
bmp_info_header.size = sizeof(BMPInfoHeader) + sizeof(BMPColorHeader);
file_header.offset_data = sizeof(BMPFileHeader) +
sizeof(BMPInfoHeader) +
sizeof(BMPColorHeader);
} else {
bmp_info_header.size = sizeof(BMPInfoHeader);
file_header.offset_data = sizeof(BMPFileHeader) + sizeof(BMPInfoHeader);
}
file_header.file_size = file_header.offset_data;
if (bmp_info_header.height < 0) {
return 52;
// throw std::runtime_error("The program can treat only BMP images with
// "
// "the origin in the bottom left corner!");
}
data.resize(bmp_info_header.width * bmp_info_header.height *
bmp_info_header.bit_count / 8);
// Here we check if we need to take into account row padding
if (bmp_info_header.width % 4 == 0) {
inp.read((char *)data.data(), data.size());
file_header.file_size += static_cast<uint32_t>(data.size());
} else {
row_stride = bmp_info_header.width * bmp_info_header.bit_count / 8;
uint32_t new_stride = make_stride_aligned(4);
std::vector<uint8_t> padding_row(new_stride - row_stride);
for (int y = 0; y < bmp_info_header.height; ++y) {
inp.read((char *)(data.data() + row_stride * y), row_stride);
inp.read((char *)padding_row.data(), padding_row.size());
}
file_header.file_size +=
static_cast<uint32_t>(data.size()) +
bmp_info_header.height * static_cast<uint32_t>(padding_row.size());
}
} else {
return 53;
// throw std::runtime_error("Unable to open the input image buffer");
}
return 0;
}
BMP(int32_t width, int32_t height, bool has_alpha = true) {
if (width <= 0 || height <= 0) {
width = 1;
height = 1;
}
bmp_info_header.width = width;
bmp_info_header.height = height;
if (has_alpha) {
bmp_info_header.size = sizeof(BMPInfoHeader) + sizeof(BMPColorHeader);
file_header.offset_data = sizeof(BMPFileHeader) + sizeof(BMPInfoHeader) +
sizeof(BMPColorHeader);
bmp_info_header.bit_count = 32;
bmp_info_header.compression = 3;
row_stride = width * 4;
data.resize(row_stride * height);
file_header.file_size = file_header.offset_data + data.size();
} else {
bmp_info_header.size = sizeof(BMPInfoHeader);
file_header.offset_data = sizeof(BMPFileHeader) + sizeof(BMPInfoHeader);
bmp_info_header.bit_count = 24;
bmp_info_header.compression = 0;
row_stride = width * 3;
data.resize(row_stride * height);
uint32_t new_stride = make_stride_aligned(4);
file_header.file_size =
file_header.offset_data + static_cast<uint32_t>(data.size()) +
bmp_info_header.height * (new_stride - row_stride);
}
}
unsigned write(const char *fname) {
std::ofstream of{fname, std::ios_base::binary};
if (of) {
if (bmp_info_header.bit_count == 32) {
write_headers_and_data(of);
} else if (bmp_info_header.bit_count == 24) {
if (bmp_info_header.width % 4 == 0) {
write_headers_and_data(of);
} else {
uint32_t new_stride = make_stride_aligned(4);
std::vector<uint8_t> padding_row(new_stride - row_stride);
write_headers(of);
for (int y = 0; y < bmp_info_header.height; ++y) {
of.write((const char *)(data.data() + row_stride * y), row_stride);
of.write((const char *)padding_row.data(), padding_row.size());
}
}
} else {
return 54; // throw std::runtime_error("The program can treat only 24 or
// 32 bits per pixel BMP files");
}
} else {
return 55; // throw std::runtime_error("Unable to open the output image
// file.");
}
return 0;
}
std::vector<unsigned char> DATA() {
std::stringstream ss;
if (ss) {
if (bmp_info_header.bit_count == 32) {
write_headers_and_datass(ss);
} else if (bmp_info_header.bit_count == 24) {
if (bmp_info_header.width % 4 == 0) {
write_headers_and_datass(ss);
} else {
uint32_t new_stride = make_stride_aligned(4);
std::vector<uint8_t> padding_row(new_stride - row_stride);
write_headersss(ss);
for (int y = 0; y < bmp_info_header.height; ++y) {
ss.write((const char *)(data.data() + row_stride * y), row_stride);
ss.write((const char *)padding_row.data(), padding_row.size());
}
}
} else {
}
} else {
}
std::string test11 = ss.str();
std::vector<unsigned char> test12(test11.begin(), test11.end());
return test12;
}
unsigned fill_region(uint32_t x0, uint32_t y0, uint32_t w, uint32_t h,
uint8_t B, uint8_t G, uint8_t R, uint8_t A) {
uint32_t channels = bmp_info_header.bit_count / 8;
for (uint32_t y = y0; y < y0 + h; ++y) {
for (uint32_t x = x0; x < x0 + w; ++x) {
/*if (x + w > (uint32_t)bmp_info_header.width || y + h >
(uint32_t)bmp_info_header.height) {
//
}*/
// else{
data[channels * (y * bmp_info_header.width + x) + 0] = B;
data[channels * (y * bmp_info_header.width + x) + 1] = G;
data[channels * (y * bmp_info_header.width + x) + 2] = R;
if (channels == 4) {
data[channels * (y * bmp_info_header.width + x) + 3] = A;
}
//}
}
}
return 0;
}
void fill_region_df(uint32_t x1, uint32_t y1, uint32_t w, uint32_t h,
uint8_t B, uint8_t G, uint8_t R, uint8_t A) {
int x0 = x1;
int y0 = this->bmp_info_header.height - y1 - h;
uint32_t channels = bmp_info_header.bit_count / 8;
for (uint32_t y = y0; y < y0 + h; ++y) {
for (uint32_t x = x0; x < x0 + w; ++x) {
if ((x + w < (uint32_t)bmp_info_header.width) ||
this->bmp_info_header.height - y - h > 0) {
data[channels * (y * bmp_info_header.width + x) + 0] = B;
data[channels * (y * bmp_info_header.width + x) + 1] = G;
data[channels * (y * bmp_info_header.width + x) + 2] = R;
if (channels == 4) {
data[channels * (y * bmp_info_header.width + x) + 3] = A;
}
}
}
}
}
void manipulate_region(uint32_t x0, uint32_t y0, uint32_t w, uint32_t h,
uint8_t A) {
int choice, choice2, intensity;
cout << "What color do you want to change? " << endl;
cout << "Enter 1 for Blue, 2 for Green, 3 for Red " << endl;
cin >> choice;
cout << "To what color do you want to change it too?" << endl;
cout << "Enter 1 for Blue, 2 for Green, 3 for Red " << endl;
cin >> choice2;
cout << "Enter the intensity of the color. (From 0 to 255) " << endl;
cin >> intensity;
if (x0 + w > (uint32_t)bmp_info_header.width ||
y0 + h > (uint32_t)bmp_info_header.height) {
return; // throw std::runtime_error("The region does not fit in the
// image!");
}
uint32_t channels = bmp_info_header.bit_count / 8;
if (choice == 1 && choice2 == 1) {
for (uint32_t y = y0; y < y0 + h; ++y) {
for (uint32_t x = x0; x < x0 + w; ++x) {
cout << channels * (y * bmp_info_header.width + x) << endl;
// Make blue thing blue
if (data[channels * (y * bmp_info_header.width + x) + 0] > 80 &&
data[channels * (y * bmp_info_header.width + x) + 0] < 255) {
data[channels * (y * bmp_info_header.width + x) + 0] = intensity;
data[channels * (y * bmp_info_header.width + x) + 1] = 0;
data[channels * (y * bmp_info_header.width + x) + 2] = 0;
}
// data[channels * (y * bmp_info_header.width + x) + 0] = B;
// data[channels * (y * bmp_info_header.width + x) + 1] = G;
// data[channels * (y * bmp_info_header.width + x) + 2] = R;
if (channels == 4) {
data[channels * (y * bmp_info_header.width + x) + 3] = A;
}
}
}
}
if (choice == 1 && choice2 == 2) {
for (uint32_t y = y0; y < y0 + h; ++y) {
for (uint32_t x = x0; x < x0 + w; ++x) {
cout << channels * (y * bmp_info_header.width + x) << endl;
// Make blue thing green
if (data[channels * (y * bmp_info_header.width + x) + 0] > 80 &&
data[channels * (y * bmp_info_header.width + x) + 0] < 255) {
data[channels * (y * bmp_info_header.width + x) + 0] = 0;
data[channels * (y * bmp_info_header.width + x) + 1] = intensity;
data[channels * (y * bmp_info_header.width + x) + 2] = 0;
}
if (channels == 4) {
data[channels * (y * bmp_info_header.width + x) + 3] = A;
}
}
}
}
if (choice == 1 && choice2 == 3) {
for (uint32_t y = y0; y < y0 + h; ++y) {
for (uint32_t x = x0; x < x0 + w; ++x) {
cout << channels * (y * bmp_info_header.width + x) << endl;
// Make blue thing red
if (data[channels * (y * bmp_info_header.width + x) + 0] > 80 &&
data[channels * (y * bmp_info_header.width + x) + 0] < 255) {
data[channels * (y * bmp_info_header.width + x) + 0] = 0;
data[channels * (y * bmp_info_header.width + x) + 1] = 0;
data[channels * (y * bmp_info_header.width + x) + 2] = intensity;
}
if (channels == 4) {
data[channels * (y * bmp_info_header.width + x) + 3] = A;
}
}
}
}
if (choice == 2 && choice2 == 1) {
for (uint32_t y = y0; y < y0 + h; ++y) {
for (uint32_t x = x0; x < x0 + w; ++x) {
cout << channels * (y * bmp_info_header.width + x) << endl;
// Make green thing blue
if (data[channels * (y * bmp_info_header.width + x) + 1] > 80 &&
data[channels * (y * bmp_info_header.width + x) + 1] < 255) {
data[channels * (y * bmp_info_header.width + x) + 0] = intensity;
data[channels * (y * bmp_info_header.width + x) + 1] = 0;
data[channels * (y * bmp_info_header.width + x) + 2] = 0;
}
if (channels == 4) {
data[channels * (y * bmp_info_header.width + x) + 3] = A;
}
}
}
}
if (choice == 2 && choice2 == 2) {
for (uint32_t y = y0; y < y0 + h; ++y) {
for (uint32_t x = x0; x < x0 + w; ++x) {
cout << channels * (y * bmp_info_header.width + x) << endl;
// Make green thing green
if (data[channels * (y * bmp_info_header.width + x) + 1] > 80 &&
data[channels * (y * bmp_info_header.width + x) + 1] < 255) {
data[channels * (y * bmp_info_header.width + x) + 0] = 0;
data[channels * (y * bmp_info_header.width + x) + 1] = intensity;
data[channels * (y * bmp_info_header.width + x) + 2] = 0;
}
if (channels == 4) {
data[channels * (y * bmp_info_header.width + x) + 3] = A;
}
}
}
}
if (choice == 2 && choice2 == 3) {
for (uint32_t y = y0; y < y0 + h; ++y) {
for (uint32_t x = x0; x < x0 + w; ++x) {
cout << channels * (y * bmp_info_header.width + x) << endl;
// Make green thing red
if (data[channels * (y * bmp_info_header.width + x) + 1] > 80 &&
data[channels * (y * bmp_info_header.width + x) + 1] < 255) {
data[channels * (y * bmp_info_header.width + x) + 0] = 0;
data[channels * (y * bmp_info_header.width + x) + 1] = 0;
data[channels * (y * bmp_info_header.width + x) + 2] = intensity;
}
if (channels == 4) {
data[channels * (y * bmp_info_header.width + x) + 3] = A;
}
}
}
}
if (choice == 3 && choice2 == 1) {
for (uint32_t y = y0; y < y0 + h; ++y) {
for (uint32_t x = x0; x < x0 + w; ++x) {
cout << channels * (y * bmp_info_header.width + x) << endl;
// Make red thing blue
if (data[channels * (y * bmp_info_header.width + x) + 2] > 80 &&
data[channels * (y * bmp_info_header.width + x) + 2] < 255) {
data[channels * (y * bmp_info_header.width + x) + 0] = intensity;
data[channels * (y * bmp_info_header.width + x) + 1] = 0;
data[channels * (y * bmp_info_header.width + x) + 2] = 0;
}
if (channels == 4) {
data[channels * (y * bmp_info_header.width + x) + 3] = A;
}
}
}
}
if (choice == 3 && choice2 == 2) {
for (uint32_t y = y0; y < y0 + h; ++y) {
for (uint32_t x = x0; x < x0 + w; ++x) {
cout << channels * (y * bmp_info_header.width + x) << endl;
// Make red thing green
if (data[channels * (y * bmp_info_header.width + x) + 2] > 80 &&
data[channels * (y * bmp_info_header.width + x) + 2] < 255) {
data[channels * (y * bmp_info_header.width + x) + 0] = 0;
data[channels * (y * bmp_info_header.width + x) + 1] = intensity;
data[channels * (y * bmp_info_header.width + x) + 2] = 0;
}
if (channels == 4) {
data[channels * (y * bmp_info_header.width + x) + 3] = A;
}
}
}
}
if (choice == 3 && choice2 == 3) {
for (uint32_t y = y0; y < y0 + h; ++y) {
for (uint32_t x = x0; x < x0 + w; ++x) {
cout << channels * (y * bmp_info_header.width + x) << endl;
// Make red thing blue
if (data[channels * (y * bmp_info_header.width + x) + 2] > 80 &&
data[channels * (y * bmp_info_header.width + x) + 2] < 255) {
data[channels * (y * bmp_info_header.width + x) + 0] = 0;
data[channels * (y * bmp_info_header.width + x) + 1] = 0;
data[channels * (y * bmp_info_header.width + x) + 2] = intensity;
}
if (channels == 4) {
data[channels * (y * bmp_info_header.width + x) + 3] = A;
}
}
}
}
}
unsigned set_pixel(uint32_t x0, uint32_t y0, uint8_t B, uint8_t G, uint8_t R,
uint8_t A) {
if (x0 >= (uint32_t)bmp_info_header.width ||
y0 >= (uint32_t)bmp_info_header.height || x0 < 0 || y0 < 0) {
return 59;
// std::string errr = "The point is outside the image boundaries! -> " +
// std::to_string(x0) + "," + std::to_string(y0); throw
// std::runtime_error(errr);
}
uint32_t channels = bmp_info_header.bit_count / 8;
data[channels * (y0 * bmp_info_header.width + x0) + 0] = B;
data[channels * (y0 * bmp_info_header.width + x0) + 1] = G;
data[channels * (y0 * bmp_info_header.width + x0) + 2] = R;
if (channels == 4) {
data[channels * (y0 * bmp_info_header.width + x0) + 3] = A;
}
return 0;
}
void set_pixel_df(uint32_t x0, uint32_t y0, uint8_t B, uint8_t G, uint8_t R,
uint8_t A) {
uint32_t y1 = this->bmp_info_header.height - y0;
if (x0 >= (uint32_t)bmp_info_header.width ||
y1 <= (uint32_t)bmp_info_header.width || x0 < 0 || y0 > 0) {
return;
// throw std::runtime_error("The point is outside the image boundaries! ->
// " + std::to_string(x0) + "," + std::to_string(y1));
}
uint32_t channels = bmp_info_header.bit_count / 8;
data[channels * (y0 * bmp_info_header.width + x0) + 0] = B;
data[channels * (y0 * bmp_info_header.width + x0) + 1] = G;
data[channels * (y0 * bmp_info_header.width + x0) + 2] = R;
if (channels == 4) {
data[channels * (y0 * bmp_info_header.width + x0) + 3] = A;
}
}
uint32_t get_pixel(uint32_t x0, uint32_t y0) {
if (x0 >= (uint32_t)bmp_info_header.width ||
y0 >= (uint32_t)bmp_info_header.height || x0 < 0 || y0 < 0) {
return 59; // throw std::runtime_error("The point is outside the image
// boundaries!");
}
uint32_t channels = bmp_info_header.bit_count / 8;
uint32_t outcol = 0;
uint8_t red = 0;
uint8_t green = 0;
uint8_t blue = 0;
uint8_t alpha = 255;
blue = data[channels * (y0 * bmp_info_header.width + x0) + 0];
green = data[channels * (y0 * bmp_info_header.width + x0) + 1];
red = data[channels * (y0 * bmp_info_header.width + x0) + 2];
if (channels == 4) {
alpha = data[channels * (y0 * bmp_info_header.width + x0) + 3];
}
outcol = ((red << 24) | (green << 16) | (blue << 8) | alpha);
return outcol;
}
uint32_t get_pixel_df(uint32_t x0, uint32_t y0) {
uint32_t y1 = this->bmp_info_header.height - y0;
if (x0 >= (uint32_t)bmp_info_header.width ||
y1 <= (uint32_t)bmp_info_header.width || x0 < 0 || y0 > 0) {
return 0; // throw std::runtime_error("The point is outside the image
// boundaries!");
}
uint32_t channels = bmp_info_header.bit_count / 8;
uint32_t outcol = 0;
uint8_t red = 0;
uint8_t green = 0;
uint8_t blue = 0;
uint8_t alpha = 255;
blue = data[channels * (y0 * bmp_info_header.width + x0) + 0];
green = data[channels * (y0 * bmp_info_header.width + x0) + 1];
red = data[channels * (y0 * bmp_info_header.width + x0) + 2];
if (channels == 4) {
alpha = data[channels * (y0 * bmp_info_header.width + x0) + 3];
}
outcol = ((red << 24) | (green << 16) | (blue << 8) | alpha);
return outcol;
}
unsigned draw_rectangle(uint32_t x0, uint32_t y0, uint32_t w, uint32_t h,
uint8_t B, uint8_t G, uint8_t R, uint8_t A,
uint8_t line_w) {
if (x0 + w > (uint32_t)bmp_info_header.width ||
y0 + h > (uint32_t)bmp_info_header.height) {
return 59; // throw std::runtime_error("The rectangle does not fit in the
// image!");
}
fill_region(x0, y0, w, line_w, B, G, R, A); // top line
fill_region(x0, (y0 + h - line_w), w, line_w, B, G, R, A); // bottom line
fill_region((x0 + w - line_w), (y0 + line_w), line_w, (h - (2 * line_w)), B,
G, R, A); // right line
fill_region(x0, (y0 + line_w), line_w, (h - (2 * line_w)), B, G, R,
A); // left line
return 0;
}
void draw_rectangle_df(uint32_t x0, uint32_t y0, uint32_t w, uint32_t h,
uint8_t B, uint8_t G, uint8_t R, uint8_t A,
uint8_t line_w) {
if (x0 + w > (uint32_t)bmp_info_header.width ||
y0 + h > (uint32_t)bmp_info_header.height) {
return; // throw std::runtime_error("The rectangle does not fit in the
// image!");
}
fill_region_df(x0, y0, w, line_w, B, G, R, A); // top line
fill_region_df(x0, (y0 + h - line_w), w, line_w, B, G, R, A); // bottom line
fill_region_df((x0 + w - line_w), (y0 + line_w), line_w, (h - (2 * line_w)),
B, G, R, A); // right line
fill_region_df(x0, (y0 + line_w), line_w, (h - (2 * line_w)), B, G, R,
A); // left line
}
private:
uint32_t row_stride{0};
void write_headers(std::ofstream &of) {
of.write((const char *)&file_header, sizeof(file_header));
of.write((const char *)&bmp_info_header, sizeof(bmp_info_header));
if (bmp_info_header.bit_count == 32) {
of.write((const char *)&bmp_color_header, sizeof(bmp_color_header));
}
}
void write_headers_and_data(std::ofstream &of) {
write_headers(of);
of.write((const char *)data.data(), data.size());
}
void write_headersss(std::stringstream &of) {
of.write((const char *)&file_header, sizeof(file_header));
of.write((const char *)&bmp_info_header, sizeof(bmp_info_header));
if (bmp_info_header.bit_count == 32) {
of.write((const char *)&bmp_color_header, sizeof(bmp_color_header));
}
}
void write_headers_and_datass(std::stringstream &of) {
write_headersss(of);
of.write((const char *)data.data(), data.size());
}
// Add 1 to the row_stride until it is divisible with align_stride
uint32_t make_stride_aligned(uint32_t align_stride) {
uint32_t new_stride = row_stride;
while (new_stride % align_stride != 0) {
new_stride++;
}
return new_stride;
}
// Check if the pixel data is stored as BGRA and if the color space type is
// sRGB
void check_color_header(BMPColorHeader &bmp_color_header) {
BMPColorHeader expected_color_header;
if (expected_color_header.red_mask != bmp_color_header.red_mask ||
expected_color_header.blue_mask != bmp_color_header.blue_mask ||
expected_color_header.green_mask != bmp_color_header.green_mask ||
expected_color_header.alpha_mask != bmp_color_header.alpha_mask) {
return; // throw std::runtime_error("Unexpected color mask format! The
// program expects the pixel data to be in the BGRA format");
}
if (expected_color_header.color_space_type !=
bmp_color_header.color_space_type) {
return; // throw std::runtime_error("Unexpected color space type! The
// program expects sRGB values");
}
}
};
@@ -0,0 +1,21 @@
#pragma once
#include <renderd7/external/lodepng.h>
#include <iostream>
namespace BitmapConverter {
/// returns 0 if all went ok, non-0 if error
/// output image is always given in RGBA (with alpha channel), even if it's a
/// BMP without alpha channel
unsigned decodeBMP(std::vector<unsigned char> &image, unsigned &w, unsigned &h,
const std::vector<unsigned char> &bmp);
/// @brief Convert A File
/// @param filename
/// @return data
std::vector<unsigned char> ConvertFile(std::string filename);
/// @brief Convert data
/// @param data
/// @return data
std::vector<unsigned char> ConvertData(std::vector<unsigned char> data);
} // namespace BitmapConverter
+187
View File
@@ -0,0 +1,187 @@
/*
This file was autogenerated by raw2c.
Visit http://www.devkitpro.org
*/
//---------------------------------------------------------------------------------
#ifndef _debugfont_h_
#define _debugfont_h_
//---------------------------------------------------------------------------------
static const unsigned char debugfont[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x81, 0xa5, 0x81,
0xbd, 0x99, 0x81, 0x7e, 0x7e, 0xff, 0xdb, 0xff, 0xc3, 0xe7, 0xff, 0x7e,
0x6c, 0xfe, 0xfe, 0xfe, 0x7c, 0x38, 0x10, 0x00, 0x10, 0x38, 0x7c, 0xfe,
0x7c, 0x38, 0x10, 0x00, 0x3c, 0x3c, 0x18, 0xff, 0xe7, 0x18, 0x3c, 0x00,
0x10, 0x38, 0x7c, 0xfe, 0xee, 0x10, 0x38, 0x00, 0x00, 0x00, 0x18, 0x3c,
0x3c, 0x18, 0x00, 0x00, 0xff, 0xff, 0xe7, 0xc3, 0xc3, 0xe7, 0xff, 0xff,
0x00, 0x3c, 0x66, 0x42, 0x42, 0x66, 0x3c, 0x00, 0xff, 0xc3, 0x99, 0xbd,
0xbd, 0x99, 0xc3, 0xff, 0x0f, 0x07, 0x0f, 0x7d, 0xcc, 0xcc, 0xcc, 0x78,
0x3c, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x7e, 0x18, 0x08, 0x0c, 0x0a, 0x0a,
0x08, 0x78, 0xf0, 0x00, 0x18, 0x14, 0x1a, 0x16, 0x72, 0xe2, 0x0e, 0x1c,
0x10, 0x54, 0x38, 0xee, 0x38, 0x54, 0x10, 0x00, 0x80, 0xe0, 0xf8, 0xfe,
0xf8, 0xe0, 0x80, 0x00, 0x02, 0x0e, 0x3e, 0xfe, 0x3e, 0x0e, 0x02, 0x00,
0x18, 0x3c, 0x5a, 0x18, 0x5a, 0x3c, 0x18, 0x00, 0x66, 0x66, 0x66, 0x66,
0x66, 0x00, 0x66, 0x00, 0x7f, 0xdb, 0xdb, 0xdb, 0x7b, 0x1b, 0x1b, 0x00,
0x1c, 0x22, 0x38, 0x44, 0x44, 0x38, 0x88, 0x70, 0x00, 0x00, 0x00, 0x00,
0x7e, 0x7e, 0x7e, 0x00, 0x18, 0x3c, 0x5a, 0x18, 0x5a, 0x3c, 0x18, 0x7e,
0x18, 0x3c, 0x5a, 0x18, 0x18, 0x18, 0x18, 0x00, 0x18, 0x18, 0x18, 0x18,
0x5a, 0x3c, 0x18, 0x00, 0x00, 0x18, 0x0c, 0xfe, 0x0c, 0x18, 0x00, 0x00,
0x00, 0x30, 0x60, 0xfe, 0x60, 0x30, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0,
0xc0, 0xfe, 0x00, 0x00, 0x00, 0x24, 0x42, 0xff, 0x42, 0x24, 0x00, 0x00,
0x00, 0x10, 0x38, 0x7c, 0xfe, 0xfe, 0x00, 0x00, 0x00, 0xfe, 0xfe, 0x7c,
0x38, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x18, 0x3c, 0x3c, 0x18, 0x18, 0x00, 0x18, 0x00, 0x6c, 0x24, 0x24, 0x00,
0x00, 0x00, 0x00, 0x00, 0x6c, 0x6c, 0xfe, 0x6c, 0xfe, 0x6c, 0x6c, 0x00,
0x10, 0x7c, 0xd0, 0x7c, 0x16, 0xfc, 0x10, 0x00, 0x00, 0x66, 0xac, 0xd8,
0x36, 0x6a, 0xcc, 0x00, 0x38, 0x4c, 0x38, 0x78, 0xce, 0xcc, 0x7a, 0x00,
0x30, 0x10, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x30, 0x60, 0x60,
0x60, 0x30, 0x18, 0x00, 0x60, 0x30, 0x18, 0x18, 0x18, 0x30, 0x60, 0x00,
0x00, 0x66, 0x3c, 0xff, 0x3c, 0x66, 0x00, 0x00, 0x00, 0x30, 0x30, 0xfc,
0x30, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x10, 0x20,
0x00, 0x00, 0x00, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x30, 0x00, 0x02, 0x06, 0x0c, 0x18, 0x30, 0x60, 0xc0, 0x00,
0x7c, 0xce, 0xde, 0xf6, 0xe6, 0xe6, 0x7c, 0x00, 0x18, 0x38, 0x78, 0x18,
0x18, 0x18, 0x7e, 0x00, 0x7c, 0xc6, 0x06, 0x1c, 0x70, 0xc6, 0xfe, 0x00,
0x7c, 0xc6, 0x06, 0x3c, 0x06, 0xc6, 0x7c, 0x00, 0x1c, 0x3c, 0x6c, 0xcc,
0xfe, 0x0c, 0x1e, 0x00, 0xfe, 0xc0, 0xfc, 0x06, 0x06, 0xc6, 0x7c, 0x00,
0x7c, 0xc6, 0xc0, 0xfc, 0xc6, 0xc6, 0x7c, 0x00, 0xfe, 0xc6, 0x0c, 0x18,
0x30, 0x30, 0x30, 0x00, 0x7c, 0xc6, 0xc6, 0x7c, 0xc6, 0xc6, 0x7c, 0x00,
0x7c, 0xc6, 0xc6, 0x7e, 0x06, 0xc6, 0x7c, 0x00, 0x00, 0x30, 0x00, 0x00,
0x00, 0x30, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x30, 0x10, 0x20,
0x0c, 0x18, 0x30, 0x60, 0x30, 0x18, 0x0c, 0x00, 0x00, 0x00, 0x7e, 0x00,
0x00, 0x7e, 0x00, 0x00, 0x60, 0x30, 0x18, 0x0c, 0x18, 0x30, 0x60, 0x00,
0x78, 0xcc, 0x0c, 0x18, 0x30, 0x00, 0x30, 0x00, 0x7c, 0x82, 0x9e, 0xa6,
0x9e, 0x80, 0x7c, 0x00, 0x7c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0x00,
0xfc, 0x66, 0x66, 0x7c, 0x66, 0x66, 0xfc, 0x00, 0x7c, 0xc6, 0xc0, 0xc0,
0xc0, 0xc6, 0x7c, 0x00, 0xfc, 0x66, 0x66, 0x66, 0x66, 0x66, 0xfc, 0x00,
0xfe, 0x62, 0x68, 0x78, 0x68, 0x62, 0xfe, 0x00, 0xfe, 0x62, 0x68, 0x78,
0x68, 0x60, 0xf0, 0x00, 0x7c, 0xc6, 0xc6, 0xc0, 0xce, 0xc6, 0x7e, 0x00,
0xc6, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0x00, 0x3c, 0x18, 0x18, 0x18,
0x18, 0x18, 0x3c, 0x00, 0x1e, 0x0c, 0x0c, 0x0c, 0xcc, 0xcc, 0x78, 0x00,
0xe6, 0x66, 0x6c, 0x78, 0x6c, 0x66, 0xe6, 0x00, 0xf0, 0x60, 0x60, 0x60,
0x62, 0x66, 0xfe, 0x00, 0x82, 0xc6, 0xee, 0xfe, 0xd6, 0xc6, 0xc6, 0x00,
0xc6, 0xe6, 0xf6, 0xde, 0xce, 0xc6, 0xc6, 0x00, 0x7c, 0xc6, 0xc6, 0xc6,
0xc6, 0xc6, 0x7c, 0x00, 0xfc, 0x66, 0x66, 0x7c, 0x60, 0x60, 0xf0, 0x00,
0x7c, 0xc6, 0xc6, 0xc6, 0xd6, 0xde, 0x7c, 0x06, 0xfc, 0x66, 0x66, 0x7c,
0x66, 0x66, 0xe6, 0x00, 0x7c, 0xc6, 0xc0, 0x7c, 0x06, 0xc6, 0x7c, 0x00,
0x7e, 0x5a, 0x5a, 0x18, 0x18, 0x18, 0x3c, 0x00, 0xc6, 0xc6, 0xc6, 0xc6,
0xc6, 0xc6, 0x7c, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0x6c, 0x38, 0x10, 0x00,
0xc6, 0xc6, 0xd6, 0xfe, 0xee, 0xc6, 0x82, 0x00, 0xc6, 0x6c, 0x38, 0x38,
0x38, 0x6c, 0xc6, 0x00, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x18, 0x3c, 0x00,
0xfe, 0xc6, 0x8c, 0x18, 0x32, 0x66, 0xfe, 0x00, 0x78, 0x60, 0x60, 0x60,
0x60, 0x60, 0x78, 0x00, 0xc0, 0x60, 0x30, 0x18, 0x0c, 0x06, 0x02, 0x00,
0x78, 0x18, 0x18, 0x18, 0x18, 0x18, 0x78, 0x00, 0x10, 0x38, 0x6c, 0xc6,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff,
0x30, 0x20, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x0c,
0x7c, 0xcc, 0x76, 0x00, 0xe0, 0x60, 0x60, 0x7c, 0x66, 0x66, 0x7c, 0x00,
0x00, 0x00, 0x7c, 0xc6, 0xc0, 0xc6, 0x7c, 0x00, 0x1c, 0x0c, 0x0c, 0x7c,
0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0x7c, 0x00,
0x1c, 0x36, 0x30, 0x78, 0x30, 0x30, 0x78, 0x00, 0x00, 0x00, 0x76, 0xcc,
0xcc, 0x7c, 0x0c, 0x78, 0xe0, 0x60, 0x6c, 0x76, 0x66, 0x66, 0xe6, 0x00,
0x18, 0x00, 0x38, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x0c, 0x00, 0x1c,
0x0c, 0x0c, 0xcc, 0x78, 0xe0, 0x60, 0x66, 0x6c, 0x78, 0x6c, 0xe6, 0x00,
0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0xcc, 0xfe,
0xd6, 0xd6, 0xd6, 0x00, 0x00, 0x00, 0xdc, 0x66, 0x66, 0x66, 0x66, 0x00,
0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0xdc, 0x66,
0x66, 0x7c, 0x60, 0xf0, 0x00, 0x00, 0x7c, 0xcc, 0xcc, 0x7c, 0x0c, 0x1e,
0x00, 0x00, 0xde, 0x76, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x7c, 0xc0,
0x7c, 0x06, 0x7c, 0x00, 0x10, 0x30, 0xfc, 0x30, 0x30, 0x34, 0x18, 0x00,
0x00, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0xc6, 0xc6,
0x6c, 0x38, 0x10, 0x00, 0x00, 0x00, 0xc6, 0xd6, 0xd6, 0xfe, 0x6c, 0x00,
0x00, 0x00, 0xc6, 0x6c, 0x38, 0x6c, 0xc6, 0x00, 0x00, 0x00, 0xcc, 0xcc,
0xcc, 0x7c, 0x0c, 0xf8, 0x00, 0x00, 0xfc, 0x98, 0x30, 0x64, 0xfc, 0x00,
0x0e, 0x18, 0x18, 0x30, 0x18, 0x18, 0x0e, 0x00, 0x18, 0x18, 0x18, 0x00,
0x18, 0x18, 0x18, 0x00, 0xe0, 0x30, 0x30, 0x18, 0x30, 0x30, 0xe0, 0x00,
0x76, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x6c,
0xc6, 0xc6, 0xfe, 0x00, 0x7c, 0xc6, 0xc0, 0xc0, 0xc6, 0x7c, 0x18, 0x70,
0xcc, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x0e, 0x10, 0x7c, 0xc6,
0xfe, 0xc0, 0x7c, 0x00, 0x7c, 0x82, 0x38, 0x0c, 0x7c, 0xcc, 0x76, 0x00,
0xcc, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0x76, 0x00, 0xe0, 0x10, 0x78, 0x0c,
0x7c, 0xcc, 0x76, 0x00, 0x30, 0x30, 0x78, 0x0c, 0x7c, 0xcc, 0x76, 0x00,
0x00, 0x00, 0x7c, 0xc0, 0xc0, 0x7c, 0x18, 0x70, 0x7c, 0x82, 0x7c, 0xc6,
0xfe, 0xc0, 0x7c, 0x00, 0xc6, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0x7c, 0x00,
0xe0, 0x10, 0x7c, 0xc6, 0xfe, 0xc0, 0x7c, 0x00, 0x66, 0x00, 0x38, 0x18,
0x18, 0x18, 0x3c, 0x00, 0x7c, 0x82, 0x38, 0x18, 0x18, 0x18, 0x3c, 0x00,
0xe0, 0x10, 0x38, 0x18, 0x18, 0x18, 0x3c, 0x00, 0xc6, 0x00, 0x7c, 0xc6,
0xfe, 0xc6, 0xc6, 0x00, 0x38, 0x38, 0x7c, 0xc6, 0xfe, 0xc6, 0xc6, 0x00,
0x0e, 0x10, 0xfe, 0x60, 0x78, 0x60, 0xfe, 0x00, 0x00, 0x00, 0x7c, 0x12,
0x7e, 0xd0, 0x7e, 0x00, 0x7e, 0xc8, 0xc8, 0xfe, 0xc8, 0xc8, 0xce, 0x00,
0x7c, 0x82, 0x7c, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0xc6, 0x00, 0x7c, 0xc6,
0xc6, 0xc6, 0x7c, 0x00, 0xe0, 0x10, 0x7c, 0xc6, 0xc6, 0xc6, 0x7c, 0x00,
0x7c, 0x82, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0xe0, 0x10, 0xcc, 0xcc,
0xcc, 0xcc, 0x76, 0x00, 0xcc, 0x00, 0xcc, 0xcc, 0xcc, 0x7c, 0x0c, 0xf8,
0xc6, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0xc6, 0x00, 0xc6, 0xc6,
0xc6, 0xc6, 0x7c, 0x00, 0x18, 0x7c, 0xd6, 0xd0, 0xd6, 0x7c, 0x18, 0x00,
0x38, 0x6c, 0x60, 0xf0, 0x60, 0xf2, 0xdc, 0x00, 0x66, 0x3c, 0x18, 0x7e,
0x18, 0x7e, 0x18, 0x00, 0xf8, 0xcc, 0xf8, 0xc4, 0xcc, 0xde, 0xcc, 0x06,
0x0e, 0x1b, 0x18, 0x3c, 0x18, 0x18, 0xd8, 0x70, 0x0e, 0x10, 0x78, 0x0c,
0x7c, 0xcc, 0x76, 0x00, 0x0e, 0x10, 0x38, 0x18, 0x18, 0x18, 0x3c, 0x00,
0x0e, 0x10, 0x7c, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x0e, 0x10, 0xcc, 0xcc,
0xcc, 0xcc, 0x76, 0x00, 0x66, 0x98, 0xdc, 0x66, 0x66, 0x66, 0x66, 0x00,
0x66, 0x98, 0xe6, 0xf6, 0xde, 0xce, 0xc6, 0x00, 0x38, 0x0c, 0x3c, 0x34,
0x00, 0x7e, 0x00, 0x00, 0x38, 0x6c, 0x6c, 0x38, 0x00, 0x7c, 0x00, 0x00,
0x30, 0x00, 0x30, 0x60, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0xfc,
0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x0c, 0x0c, 0x00, 0x00,
0xc0, 0xc8, 0xd0, 0xfe, 0x46, 0x8c, 0x1e, 0x00, 0xc0, 0xc8, 0xd0, 0xec,
0x5c, 0xbe, 0x0c, 0x00, 0x18, 0x00, 0x18, 0x18, 0x3c, 0x3c, 0x18, 0x00,
0x00, 0x36, 0x6c, 0xd8, 0x6c, 0x36, 0x00, 0x00, 0x00, 0xd8, 0x6c, 0x36,
0x6c, 0xd8, 0x00, 0x00, 0x22, 0x88, 0x22, 0x88, 0x22, 0x88, 0x22, 0x88,
0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0xdb, 0x77, 0xdb, 0xee,
0xdb, 0x77, 0xdb, 0xee, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
0x18, 0x18, 0x18, 0x18, 0xf8, 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0x18,
0xf8, 0x18, 0x18, 0x18, 0x36, 0x36, 0x36, 0x36, 0xf6, 0x36, 0x36, 0x36,
0x00, 0x00, 0x00, 0x00, 0xfe, 0x36, 0x36, 0x36, 0x00, 0x00, 0xf8, 0x18,
0xf8, 0x18, 0x18, 0x18, 0x36, 0x36, 0xf6, 0x06, 0xf6, 0x36, 0x36, 0x36,
0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x00, 0x00, 0xfe, 0x06,
0xf6, 0x36, 0x36, 0x36, 0x36, 0x36, 0xf6, 0x06, 0xfe, 0x00, 0x00, 0x00,
0x36, 0x36, 0x36, 0x36, 0xfe, 0x00, 0x00, 0x00, 0x18, 0x18, 0xf8, 0x18,
0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x18, 0x18, 0x18,
0x18, 0x18, 0x18, 0x18, 0x1f, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18,
0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x18, 0x18, 0x18,
0x18, 0x18, 0x18, 0x18, 0x1f, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00,
0xff, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0xff, 0x18, 0x18, 0x18,
0x18, 0x18, 0x1f, 0x18, 0x1f, 0x18, 0x18, 0x18, 0x36, 0x36, 0x36, 0x36,
0x37, 0x36, 0x36, 0x36, 0x36, 0x36, 0x37, 0x30, 0x3f, 0x00, 0x00, 0x00,
0x00, 0x00, 0x3f, 0x30, 0x37, 0x36, 0x36, 0x36, 0x36, 0x36, 0xf7, 0x00,
0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0xf7, 0x36, 0x36, 0x36,
0x36, 0x36, 0x37, 0x30, 0x37, 0x36, 0x36, 0x36, 0x00, 0x00, 0xff, 0x00,
0xff, 0x00, 0x00, 0x00, 0x36, 0x36, 0xf7, 0x00, 0xf7, 0x36, 0x36, 0x36,
0x18, 0x18, 0xff, 0x00, 0xff, 0x00, 0x00, 0x00, 0x36, 0x36, 0x36, 0x36,
0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0xff, 0x18, 0x18, 0x18,
0x00, 0x00, 0x00, 0x00, 0xff, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
0x3f, 0x00, 0x00, 0x00, 0x18, 0x18, 0x1f, 0x18, 0x1f, 0x00, 0x00, 0x00,
0x00, 0x00, 0x1f, 0x18, 0x1f, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00,
0x3f, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xff, 0x36, 0x36, 0x36,
0x18, 0x18, 0xff, 0x18, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x18, 0x18, 0x18,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
0xff, 0xff, 0xff, 0xff, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0,
0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0xff, 0xff, 0xff, 0xff,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x74, 0xcc, 0xc8, 0xdc, 0x76, 0x00,
0x78, 0xcc, 0xd8, 0xcc, 0xc6, 0xc6, 0xdc, 0x40, 0xfe, 0x62, 0x60, 0x60,
0x60, 0x60, 0xf0, 0x00, 0x00, 0x02, 0x7e, 0xec, 0x6c, 0x6c, 0x48, 0x00,
0xfe, 0x62, 0x30, 0x18, 0x30, 0x62, 0xfe, 0x00, 0x00, 0x00, 0x7e, 0xd0,
0xc8, 0xc8, 0x70, 0x00, 0x00, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xf8, 0x80,
0x00, 0x00, 0x7e, 0xd8, 0x18, 0x18, 0x10, 0x00, 0x38, 0x10, 0x7c, 0xd6,
0xd6, 0x7c, 0x10, 0x38, 0x7c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0x7c, 0x00,
0x7c, 0xc6, 0xc6, 0xc6, 0x6c, 0x28, 0xee, 0x00, 0x3c, 0x22, 0x18, 0x7c,
0xcc, 0xcc, 0x78, 0x00, 0x00, 0x00, 0x66, 0x99, 0x99, 0x66, 0x00, 0x00,
0x00, 0x06, 0x7c, 0x9e, 0xf2, 0x7c, 0xc0, 0x00, 0x00, 0x00, 0x7c, 0xc0,
0xf8, 0xc0, 0x7c, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x00,
0x00, 0xfe, 0x00, 0xfe, 0x00, 0xfe, 0x00, 0x00, 0x18, 0x18, 0x7e, 0x18,
0x18, 0x00, 0x7e, 0x00, 0x30, 0x18, 0x0c, 0x18, 0x30, 0x00, 0x7c, 0x00,
0x18, 0x30, 0x60, 0x30, 0x18, 0x00, 0x7c, 0x00, 0x0e, 0x1b, 0x1b, 0x18,
0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xd8, 0xd8, 0x70,
0x00, 0x18, 0x00, 0x7e, 0x00, 0x18, 0x00, 0x00, 0x00, 0x76, 0xdc, 0x00,
0x76, 0xdc, 0x00, 0x00, 0x38, 0x6c, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x18, 0x00, 0x00, 0x00, 0x0f, 0x0c, 0x0c, 0x0c, 0xec, 0x6c, 0x3c, 0x00,
0xd8, 0x6c, 0x6c, 0x6c, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x30, 0xc0, 0xf0,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x3c, 0x3c, 0x3c, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
const int debugfont_size = sizeof(debugfont);
//---------------------------------------------------------------------------------
#endif //_font_h_
//---------------------------------------------------------------------------------
+422
View File
@@ -0,0 +1,422 @@
// jpgd.h - C++ class for JPEG decompression.
// Richard Geldreich <richgel99@gmail.com>
// See jpgd.cpp for license (Public Domain or Apache 2.0).
#ifndef JPEG_DECODER_H
#define JPEG_DECODER_H
#include <assert.h>
#include <cinttypes>
#include <setjmp.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#ifdef _MSC_VER
#define JPGD_NORETURN __declspec(noreturn)
#elif defined(__GNUC__)
#define JPGD_NORETURN __attribute__((noreturn))
#else
#define JPGD_NORETURN
#endif
#define JPGD_HUFF_TREE_MAX_LENGTH 512
#define JPGD_HUFF_CODE_SIZE_MAX_LENGTH 256
namespace jpgd {
typedef unsigned char uint8;
typedef signed short int16;
typedef unsigned short uint16;
typedef unsigned int uint;
typedef signed int int32;
// Loads a JPEG image from a memory buffer or a file.
// req_comps can be 1 (grayscale), 3 (RGB), or 4 (RGBA).
// On return, width/height will be set to the image's dimensions, and
// actual_comps will be set to the either 1 (grayscale) or 3 (RGB). Notes: For
// more control over where and how the source data is read, see the
// decompress_jpeg_image_from_stream() function below, or call the jpeg_decoder
// class directly. Requesting a 8 or 32bpp image is currently a little faster
// than 24bpp because the jpeg_decoder class itself currently always unpacks to
// either 8 or 32bpp.
unsigned char *decompress_jpeg_image_from_memory(const unsigned char *pSrc_data,
int src_data_size, int *width,
int *height, int *actual_comps,
int req_comps,
uint32_t flags = 0);
unsigned char *decompress_jpeg_image_from_file(const char *pSrc_filename,
int *width, int *height,
int *actual_comps, int req_comps,
uint32_t flags = 0);
// Success/failure error codes.
enum jpgd_status {
JPGD_SUCCESS = 0,
JPGD_FAILED = -1,
JPGD_DONE = 1,
JPGD_BAD_DHT_COUNTS = -256,
JPGD_BAD_DHT_INDEX,
JPGD_BAD_DHT_MARKER,
JPGD_BAD_DQT_MARKER,
JPGD_BAD_DQT_TABLE,
JPGD_BAD_PRECISION,
JPGD_BAD_HEIGHT,
JPGD_BAD_WIDTH,
JPGD_TOO_MANY_COMPONENTS,
JPGD_BAD_SOF_LENGTH,
JPGD_BAD_VARIABLE_MARKER,
JPGD_BAD_DRI_LENGTH,
JPGD_BAD_SOS_LENGTH,
JPGD_BAD_SOS_COMP_ID,
JPGD_W_EXTRA_BYTES_BEFORE_MARKER,
JPGD_NO_ARITHMITIC_SUPPORT,
JPGD_UNEXPECTED_MARKER,
JPGD_NOT_JPEG,
JPGD_UNSUPPORTED_MARKER,
JPGD_BAD_DQT_LENGTH,
JPGD_TOO_MANY_BLOCKS,
JPGD_UNDEFINED_QUANT_TABLE,
JPGD_UNDEFINED_HUFF_TABLE,
JPGD_NOT_SINGLE_SCAN,
JPGD_UNSUPPORTED_COLORSPACE,
JPGD_UNSUPPORTED_SAMP_FACTORS,
JPGD_DECODE_ERROR,
JPGD_BAD_RESTART_MARKER,
JPGD_BAD_SOS_SPECTRAL,
JPGD_BAD_SOS_SUCCESSIVE,
JPGD_STREAM_READ,
JPGD_NOTENOUGHMEM,
JPGD_TOO_MANY_SCANS
};
// Input stream interface.
// Derive from this class to read input data from sources other than files or
// memory. Set m_eof_flag to true when no more data is available. The decoder is
// rather greedy: it will keep on calling this method until its internal input
// buffer is full, or until the EOF flag is set. It the input stream contains
// data after the JPEG stream's EOI (end of image) marker it will probably be
// pulled into the internal buffer. Call the get_total_bytes_read() method to
// determine the actual size of the JPEG stream after successful decoding.
class jpeg_decoder_stream {
public:
jpeg_decoder_stream() {}
virtual ~jpeg_decoder_stream() {}
// The read() method is called when the internal input buffer is empty.
// Parameters:
// pBuf - input buffer
// max_bytes_to_read - maximum bytes that can be written to pBuf
// pEOF_flag - set this to true if at end of stream (no more bytes remaining)
// Returns -1 on error, otherwise return the number of bytes actually written
// to the buffer (which may be 0). Notes: This method will be called in a loop
// until you set *pEOF_flag to true or the internal buffer is full.
virtual int read(uint8 *pBuf, int max_bytes_to_read, bool *pEOF_flag) = 0;
};
// stdio FILE stream class.
class jpeg_decoder_file_stream : public jpeg_decoder_stream {
jpeg_decoder_file_stream(const jpeg_decoder_file_stream &);
jpeg_decoder_file_stream &operator=(const jpeg_decoder_file_stream &);
FILE *m_pFile;
bool m_eof_flag, m_error_flag;
public:
jpeg_decoder_file_stream();
virtual ~jpeg_decoder_file_stream();
bool open(const char *Pfilename);
void close();
virtual int read(uint8 *pBuf, int max_bytes_to_read, bool *pEOF_flag);
};
// Memory stream class.
class jpeg_decoder_mem_stream : public jpeg_decoder_stream {
const uint8 *m_pSrc_data;
uint m_ofs, m_size;
public:
jpeg_decoder_mem_stream() : m_pSrc_data(NULL), m_ofs(0), m_size(0) {}
jpeg_decoder_mem_stream(const uint8 *pSrc_data, uint size)
: m_pSrc_data(pSrc_data), m_ofs(0), m_size(size) {}
virtual ~jpeg_decoder_mem_stream() {}
bool open(const uint8 *pSrc_data, uint size);
void close() {
m_pSrc_data = NULL;
m_ofs = 0;
m_size = 0;
}
virtual int read(uint8 *pBuf, int max_bytes_to_read, bool *pEOF_flag);
};
// Loads JPEG file from a jpeg_decoder_stream.
unsigned char *decompress_jpeg_image_from_stream(jpeg_decoder_stream *pStream,
int *width, int *height,
int *actual_comps,
int req_comps,
uint32_t flags = 0);
enum {
JPGD_IN_BUF_SIZE = 8192,
JPGD_MAX_BLOCKS_PER_MCU = 10,
JPGD_MAX_HUFF_TABLES = 8,
JPGD_MAX_QUANT_TABLES = 4,
JPGD_MAX_COMPONENTS = 4,
JPGD_MAX_COMPS_IN_SCAN = 4,
JPGD_MAX_BLOCKS_PER_ROW = 16384,
JPGD_MAX_HEIGHT = 32768,
JPGD_MAX_WIDTH = 32768
};
typedef int16 jpgd_quant_t;
typedef int16 jpgd_block_coeff_t;
class jpeg_decoder {
public:
enum { cFlagBoxChromaFiltering = 1, cFlagDisableSIMD = 2 };
// Call get_error_code() after constructing to determine if the stream is
// valid or not. You may call the get_width(), get_height(), etc. methods
// after the constructor is called. You may then either destruct the object,
// or begin decoding the image by calling begin_decoding(), then decode() on
// each scanline.
jpeg_decoder(jpeg_decoder_stream *pStream, uint32_t flags = 0);
~jpeg_decoder();
// Call this method after constructing the object to begin decompression.
// If JPGD_SUCCESS is returned you may then call decode() on each scanline.
int begin_decoding();
// Returns the next scan line.
// For grayscale images, pScan_line will point to a buffer containing 8-bit
// pixels (get_bytes_per_pixel() will return 1). Otherwise, it will always
// point to a buffer containing 32-bit RGBA pixels (A will always be 255, and
// get_bytes_per_pixel() will return 4). Returns JPGD_SUCCESS if a scan line
// has been returned. Returns JPGD_DONE if all scan lines have been returned.
// Returns JPGD_FAILED if an error occurred. Call get_error_code() for a more
// info.
int decode(const void **pScan_line, uint *pScan_line_len);
inline jpgd_status get_error_code() const { return m_error_code; }
inline int get_width() const { return m_image_x_size; }
inline int get_height() const { return m_image_y_size; }
inline int get_num_components() const { return m_comps_in_frame; }
inline int get_bytes_per_pixel() const { return m_dest_bytes_per_pixel; }
inline int get_bytes_per_scan_line() const {
return m_image_x_size * get_bytes_per_pixel();
}
// Returns the total number of bytes actually consumed by the decoder (which
// should equal the actual size of the JPEG file).
inline int get_total_bytes_read() const { return m_total_bytes_read; }
private:
jpeg_decoder(const jpeg_decoder &);
jpeg_decoder &operator=(const jpeg_decoder &);
typedef void (*pDecode_block_func)(jpeg_decoder *, int, int, int);
struct huff_tables {
bool ac_table;
uint look_up[256];
uint look_up2[256];
uint8 code_size[JPGD_HUFF_CODE_SIZE_MAX_LENGTH];
uint tree[JPGD_HUFF_TREE_MAX_LENGTH];
};
struct coeff_buf {
uint8 *pData;
int block_num_x, block_num_y;
int block_len_x, block_len_y;
int block_size;
};
struct mem_block {
mem_block *m_pNext;
size_t m_used_count;
size_t m_size;
char m_data[1];
};
jmp_buf m_jmp_state;
uint32_t m_flags;
mem_block *m_pMem_blocks;
int m_image_x_size;
int m_image_y_size;
jpeg_decoder_stream *m_pStream;
int m_progressive_flag;
uint8 m_huff_ac[JPGD_MAX_HUFF_TABLES];
uint8 *m_huff_num[JPGD_MAX_HUFF_TABLES]; // pointer to number of Huffman codes
// per bit size
uint8 *
m_huff_val[JPGD_MAX_HUFF_TABLES]; // pointer to Huffman codes per bit size
jpgd_quant_t
*m_quant[JPGD_MAX_QUANT_TABLES]; // pointer to quantization tables
int m_scan_type; // Gray, Yh1v1, Yh1v2, Yh2v1, Yh2v2 (CMYK111, CMYK4114 no
// longer supported)
int m_comps_in_frame; // # of components in frame
int m_comp_h_samp[JPGD_MAX_COMPONENTS]; // component's horizontal sampling
// factor
int m_comp_v_samp[JPGD_MAX_COMPONENTS]; // component's vertical sampling
// factor
int m_comp_quant[JPGD_MAX_COMPONENTS]; // component's quantization table
// selector
int m_comp_ident[JPGD_MAX_COMPONENTS]; // component's ID
int m_comp_h_blocks[JPGD_MAX_COMPONENTS];
int m_comp_v_blocks[JPGD_MAX_COMPONENTS];
int m_comps_in_scan; // # of components in scan
int m_comp_list[JPGD_MAX_COMPS_IN_SCAN]; // components in this scan
int m_comp_dc_tab[JPGD_MAX_COMPONENTS]; // component's DC Huffman coding table
// selector
int m_comp_ac_tab[JPGD_MAX_COMPONENTS]; // component's AC Huffman coding table
// selector
int m_spectral_start; // spectral selection start
int m_spectral_end; // spectral selection end
int m_successive_low; // successive approximation low
int m_successive_high; // successive approximation high
int m_max_mcu_x_size; // MCU's max. X size in pixels
int m_max_mcu_y_size; // MCU's max. Y size in pixels
int m_blocks_per_mcu;
int m_max_blocks_per_row;
int m_mcus_per_row, m_mcus_per_col;
int m_mcu_org[JPGD_MAX_BLOCKS_PER_MCU];
int m_total_lines_left; // total # lines left in image
int m_mcu_lines_left; // total # lines left in this MCU
int m_num_buffered_scanlines;
int m_real_dest_bytes_per_scan_line;
int m_dest_bytes_per_scan_line; // rounded up
int m_dest_bytes_per_pixel; // 4 (RGB) or 1 (Y)
huff_tables *m_pHuff_tabs[JPGD_MAX_HUFF_TABLES];
coeff_buf *m_dc_coeffs[JPGD_MAX_COMPONENTS];
coeff_buf *m_ac_coeffs[JPGD_MAX_COMPONENTS];
int m_eob_run;
int m_block_y_mcu[JPGD_MAX_COMPONENTS];
uint8 *m_pIn_buf_ofs;
int m_in_buf_left;
int m_tem_flag;
uint8 m_in_buf_pad_start[64];
uint8 m_in_buf[JPGD_IN_BUF_SIZE + 128];
uint8 m_in_buf_pad_end[64];
int m_bits_left;
uint m_bit_buf;
int m_restart_interval;
int m_restarts_left;
int m_next_restart_num;
int m_max_mcus_per_row;
int m_max_blocks_per_mcu;
int m_max_mcus_per_col;
uint m_last_dc_val[JPGD_MAX_COMPONENTS];
jpgd_block_coeff_t *m_pMCU_coefficients;
int m_mcu_block_max_zag[JPGD_MAX_BLOCKS_PER_MCU];
uint8 *m_pSample_buf;
uint8 *m_pSample_buf_prev;
int m_crr[256];
int m_cbb[256];
int m_crg[256];
int m_cbg[256];
uint8 *m_pScan_line_0;
uint8 *m_pScan_line_1;
jpgd_status m_error_code;
int m_total_bytes_read;
bool m_ready_flag;
bool m_eof_flag;
bool m_sample_buf_prev_valid;
bool m_has_sse2;
inline int check_sample_buf_ofs(int ofs) const {
assert(ofs >= 0);
assert(ofs < m_max_blocks_per_row * 64);
return ofs;
}
void free_all_blocks();
JPGD_NORETURN void stop_decoding(jpgd_status status);
void *alloc(size_t n, bool zero = false);
void *alloc_aligned(size_t nSize, uint32_t align = 16, bool zero = false);
void word_clear(void *p, uint16 c, uint n);
void prep_in_buffer();
void read_dht_marker();
void read_dqt_marker();
void read_sof_marker();
void skip_variable_marker();
void read_dri_marker();
void read_sos_marker();
int next_marker();
int process_markers();
void locate_soi_marker();
void locate_sof_marker();
int locate_sos_marker();
void init(jpeg_decoder_stream *pStream, uint32_t flags);
void create_look_ups();
void fix_in_buffer();
void transform_mcu(int mcu_row);
coeff_buf *coeff_buf_open(int block_num_x, int block_num_y, int block_len_x,
int block_len_y);
inline jpgd_block_coeff_t *coeff_buf_getp(coeff_buf *cb, int block_x,
int block_y);
void load_next_row();
void decode_next_row();
void make_huff_table(int index, huff_tables *pH);
void check_quant_tables();
void check_huff_tables();
bool calc_mcu_block_order();
int init_scan();
void init_frame();
void process_restart();
void decode_scan(pDecode_block_func decode_block_func);
void init_progressive();
void init_sequential();
void decode_start();
void decode_init(jpeg_decoder_stream *pStream, uint32_t flags);
void H2V2Convert();
uint32_t H2V2ConvertFiltered();
void H2V1Convert();
void H2V1ConvertFiltered();
void H1V2Convert();
void H1V2ConvertFiltered();
void H1V1Convert();
void gray_convert();
void find_eoi();
inline uint get_char();
inline uint get_char(bool *pPadding_flag);
inline void stuff_char(uint8 q);
inline uint8 get_octet();
inline uint get_bits(int num_bits);
inline uint get_bits_no_markers(int numbits);
inline int huff_decode(huff_tables *pH);
inline int huff_decode(huff_tables *pH, int &extrabits);
// Clamps a value between 0-255.
static inline uint8 clamp(int i) {
if (static_cast<uint>(i) > 255)
i = (((~i) >> 31) & 0xFF);
return static_cast<uint8>(i);
}
int decode_next_mcu_row();
static void decode_block_dc_first(jpeg_decoder *pD, int component_id,
int block_x, int block_y);
static void decode_block_dc_refine(jpeg_decoder *pD, int component_id,
int block_x, int block_y);
static void decode_block_ac_first(jpeg_decoder *pD, int component_id,
int block_x, int block_y);
static void decode_block_ac_refine(jpeg_decoder *pD, int component_id,
int block_x, int block_y);
};
} // namespace jpgd
#endif // JPEG_DECODER_H
+478
View File
@@ -0,0 +1,478 @@
// Copyright 2009 Intel Corporation
// All Rights Reserved
//
// Permission is granted to use, copy, distribute and prepare derivative works
// of this software for any purpose and without fee, provided, that the above
// copyright notice and this statement appear in all copies. Intel makes no
// representations about the suitability of this software for any purpose. THIS
// SOFTWARE IS PROVIDED "AS IS." INTEL SPECIFICALLY DISCLAIMS ALL WARRANTIES,
// EXPRESS OR IMPLIED, AND ALL LIABILITY, INCLUDING CONSEQUENTIAL AND OTHER
// INDIRECT DAMAGES, FOR THE USE OF THIS SOFTWARE, INCLUDING LIABILITY FOR
// INFRINGEMENT OF ANY PROPRIETARY RIGHTS, AND INCLUDING THE WARRANTIES OF
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. Intel does not assume
// any responsibility for any errors which may appear in this software nor any
// responsibility to update it.
//
// From:
// https://software.intel.com/sites/default/files/m/d/4/1/d/8/UsingIntelAVXToImplementIDCT-r1_5.pdf
// https://software.intel.com/file/29048
//
// Requires SSE
//
#ifdef _MSC_VER
#include <intrin.h>
#endif
#include <immintrin.h>
#ifdef _MSC_VER
#define JPGD_SIMD_ALIGN(type, name) __declspec(align(16)) type name
#else
#define JPGD_SIMD_ALIGN(type, name) type name __attribute__((aligned(16)))
#endif
#include <cinttypes>
#define BITS_INV_ACC 4
#define SHIFT_INV_ROW 16 - BITS_INV_ACC
#define SHIFT_INV_COL 1 + BITS_INV_ACC
const short IRND_INV_ROW = 1024 * (6 - BITS_INV_ACC); // 1 << (SHIFT_INV_ROW-1)
const short IRND_INV_COL = 16 * (BITS_INV_ACC - 3); // 1 << (SHIFT_INV_COL-1)
const short IRND_INV_CORR = IRND_INV_COL - 1; // correction -1.0 and round
JPGD_SIMD_ALIGN(short, shortM128_one_corr[8]) = {1, 1, 1, 1, 1, 1, 1, 1};
JPGD_SIMD_ALIGN(short, shortM128_round_inv_row[8]) = {
IRND_INV_ROW, 0, IRND_INV_ROW, 0, IRND_INV_ROW, 0, IRND_INV_ROW, 0};
JPGD_SIMD_ALIGN(short, shortM128_round_inv_col[8]) = {
IRND_INV_COL, IRND_INV_COL, IRND_INV_COL, IRND_INV_COL,
IRND_INV_COL, IRND_INV_COL, IRND_INV_COL, IRND_INV_COL};
JPGD_SIMD_ALIGN(short, shortM128_round_inv_corr[8]) = {
IRND_INV_CORR, IRND_INV_CORR, IRND_INV_CORR, IRND_INV_CORR,
IRND_INV_CORR, IRND_INV_CORR, IRND_INV_CORR, IRND_INV_CORR};
JPGD_SIMD_ALIGN(short, shortM128_tg_1_16[8]) = {
13036, 13036, 13036, 13036,
13036, 13036, 13036, 13036}; // tg * (2<<16) + 0.5
JPGD_SIMD_ALIGN(short, shortM128_tg_2_16[8]) = {
27146, 27146, 27146, 27146,
27146, 27146, 27146, 27146}; // tg * (2<<16) + 0.5
JPGD_SIMD_ALIGN(short, shortM128_tg_3_16[8]) = {
-21746, -21746, -21746, -21746,
-21746, -21746, -21746, -21746}; // tg * (2<<16) + 0.5
JPGD_SIMD_ALIGN(short, shortM128_cos_4_16[8]) = {
-19195, -19195, -19195, -19195,
-19195, -19195, -19195, -19195}; // cos * (2<<16) + 0.5
//-----------------------------------------------------------------------------
// Table for rows 0,4 - constants are multiplied on cos_4_16
// w15 w14 w11 w10 w07 w06 w03 w02
// w29 w28 w25 w24 w21 w20 w17 w16
// w31 w30 w27 w26 w23 w22 w19 w18
// movq -> w05 w04 w01 w00
JPGD_SIMD_ALIGN(short, shortM128_tab_i_04[]) = {
16384, 21407, 16384, 8867,
16384, -8867, 16384, -21407, // w13 w12 w09 w08
16384, 8867, -16384, -21407, // w07 w06 w03 w02
-16384, 21407, 16384, -8867, // w15 w14 w11 w10
22725, 19266, 19266, -4520, // w21 w20 w17 w16
12873, -22725, 4520, -12873, // w29 w28 w25 w24
12873, 4520, -22725, -12873, // w23 w22 w19 w18
4520, 19266, 19266, -22725}; // w31 w30 w27 w26
// Table for rows 1,7 - constants are multiplied on cos_1_16
// movq -> w05 w04 w01 w00
JPGD_SIMD_ALIGN(short, shortM128_tab_i_17[]) = {
22725, 29692, 22725, 12299,
22725, -12299, 22725, -29692, // w13 w12 w09 w08
22725, 12299, -22725, -29692, // w07 w06 w03 w02
-22725, 29692, 22725, -12299, // w15 w14 w11 w10
31521, 26722, 26722, -6270, // w21 w20 w17 w16
17855, -31521, 6270, -17855, // w29 w28 w25 w24
17855, 6270, -31521, -17855, // w23 w22 w19 w18
6270, 26722, 26722, -31521}; // w31 w30 w27 w26
// Table for rows 2,6 - constants are multiplied on cos_2_16
// movq -> w05 w04 w01 w00
JPGD_SIMD_ALIGN(short, shortM128_tab_i_26[]) = {
21407, 27969, 21407, 11585,
21407, -11585, 21407, -27969, // w13 w12 w09 w08
21407, 11585, -21407, -27969, // w07 w06 w03 w02
-21407, 27969, 21407, -11585, // w15 w14 w11 w10
29692, 25172, 25172, -5906, // w21 w20 w17 w16
16819, -29692, 5906, -16819, // w29 w28 w25 w24
16819, 5906, -29692, -16819, // w23 w22 w19 w18
5906, 25172, 25172, -29692}; // w31 w30 w27 w26
// Table for rows 3,5 - constants are multiplied on cos_3_16
// movq -> w05 w04 w01 w00
JPGD_SIMD_ALIGN(short, shortM128_tab_i_35[]) = {
19266, 25172, 19266, 10426,
19266, -10426, 19266, -25172, // w13 w12 w09 w08
19266, 10426, -19266, -25172, // w07 w06 w03 w02
-19266, 25172, 19266, -10426, // w15 w14 w11 w10
26722, 22654, 22654, -5315, // w21 w20 w17 w16
15137, -26722, 5315, -15137, // w29 w28 w25 w24
15137, 5315, -26722, -15137, // w23 w22 w19 w18
5315, 22654, 22654, -26722}; // w31 w30 w27 w26
JPGD_SIMD_ALIGN(short, shortM128_128[8]) = {128, 128, 128, 128,
128, 128, 128, 128};
void idctSSEShortU8(const short *pInput, uint8_t *pOutputUB) {
__m128i r_xmm0, r_xmm4;
__m128i r_xmm1, r_xmm2, r_xmm3, r_xmm5, r_xmm6, r_xmm7;
__m128i row0, row1, row2, row3, row4, row5, row6, row7;
short *pTab_i_04 = shortM128_tab_i_04;
short *pTab_i_26 = shortM128_tab_i_26;
// Get pointers for this input and output
pTab_i_04 = shortM128_tab_i_04;
pTab_i_26 = shortM128_tab_i_26;
// Row 1 and Row 3
r_xmm0 = _mm_load_si128((__m128i *)pInput);
r_xmm4 = _mm_load_si128((__m128i *)(&pInput[2 * 8]));
// *** Work on the data in xmm0
// low shuffle mask = 0xd8 = 11 01 10 00
// get short 2 and short 0 into ls 32-bits
r_xmm0 = _mm_shufflelo_epi16(r_xmm0, 0xd8);
// copy short 2 and short 0 to all locations
r_xmm1 = _mm_shuffle_epi32(r_xmm0, 0);
// add to those copies
r_xmm1 = _mm_madd_epi16(r_xmm1, *((__m128i *)pTab_i_04));
// shuffle mask = 0x55 = 01 01 01 01
// copy short 3 and short 1 to all locations
r_xmm3 = _mm_shuffle_epi32(r_xmm0, 0x55);
// high shuffle mask = 0xd8 = 11 01 10 00
// get short 6 and short 4 into bit positions 64-95
// get short 7 and short 5 into bit positions 96-127
r_xmm0 = _mm_shufflehi_epi16(r_xmm0, 0xd8);
// add to short 3 and short 1
r_xmm3 = _mm_madd_epi16(r_xmm3, *((__m128i *)&pTab_i_04[16]));
// shuffle mask = 0xaa = 10 10 10 10
// copy short 6 and short 4 to all locations
r_xmm2 = _mm_shuffle_epi32(r_xmm0, 0xaa);
// shuffle mask = 0xaa = 11 11 11 11
// copy short 7 and short 5 to all locations
r_xmm0 = _mm_shuffle_epi32(r_xmm0, 0xff);
// add to short 6 and short 4
r_xmm2 = _mm_madd_epi16(r_xmm2, *((__m128i *)&pTab_i_04[8]));
// *** Work on the data in xmm4
// high shuffle mask = 0xd8 11 01 10 00
// get short 6 and short 4 into bit positions 64-95
// get short 7 and short 5 into bit positions 96-127
r_xmm4 = _mm_shufflehi_epi16(r_xmm4, 0xd8);
// (xmm0 short 2 and short 0 plus pSi) + some constants
r_xmm1 = _mm_add_epi32(r_xmm1, *((__m128i *)shortM128_round_inv_row));
r_xmm4 = _mm_shufflelo_epi16(r_xmm4, 0xd8);
r_xmm0 = _mm_madd_epi16(r_xmm0, *((__m128i *)&pTab_i_04[24]));
r_xmm5 = _mm_shuffle_epi32(r_xmm4, 0);
r_xmm6 = _mm_shuffle_epi32(r_xmm4, 0xaa);
r_xmm5 = _mm_madd_epi16(r_xmm5, *((__m128i *)&shortM128_tab_i_26[0]));
r_xmm1 = _mm_add_epi32(r_xmm1, r_xmm2);
r_xmm2 = r_xmm1;
r_xmm7 = _mm_shuffle_epi32(r_xmm4, 0x55);
r_xmm6 = _mm_madd_epi16(r_xmm6, *((__m128i *)&shortM128_tab_i_26[8]));
r_xmm0 = _mm_add_epi32(r_xmm0, r_xmm3);
r_xmm4 = _mm_shuffle_epi32(r_xmm4, 0xff);
r_xmm2 = _mm_sub_epi32(r_xmm2, r_xmm0);
r_xmm7 = _mm_madd_epi16(r_xmm7, *((__m128i *)&shortM128_tab_i_26[16]));
r_xmm0 = _mm_add_epi32(r_xmm0, r_xmm1);
r_xmm2 = _mm_srai_epi32(r_xmm2, 12);
r_xmm5 = _mm_add_epi32(r_xmm5, *((__m128i *)shortM128_round_inv_row));
r_xmm4 = _mm_madd_epi16(r_xmm4, *((__m128i *)&shortM128_tab_i_26[24]));
r_xmm5 = _mm_add_epi32(r_xmm5, r_xmm6);
r_xmm6 = r_xmm5;
r_xmm0 = _mm_srai_epi32(r_xmm0, 12);
r_xmm2 = _mm_shuffle_epi32(r_xmm2, 0x1b);
row0 = _mm_packs_epi32(r_xmm0, r_xmm2);
r_xmm4 = _mm_add_epi32(r_xmm4, r_xmm7);
r_xmm6 = _mm_sub_epi32(r_xmm6, r_xmm4);
r_xmm4 = _mm_add_epi32(r_xmm4, r_xmm5);
r_xmm6 = _mm_srai_epi32(r_xmm6, 12);
r_xmm4 = _mm_srai_epi32(r_xmm4, 12);
r_xmm6 = _mm_shuffle_epi32(r_xmm6, 0x1b);
row2 = _mm_packs_epi32(r_xmm4, r_xmm6);
// Row 5 and row 7
r_xmm0 = _mm_load_si128((__m128i *)(&pInput[4 * 8]));
r_xmm4 = _mm_load_si128((__m128i *)(&pInput[6 * 8]));
r_xmm0 = _mm_shufflelo_epi16(r_xmm0, 0xd8);
r_xmm1 = _mm_shuffle_epi32(r_xmm0, 0);
r_xmm1 = _mm_madd_epi16(r_xmm1, *((__m128i *)pTab_i_04));
r_xmm3 = _mm_shuffle_epi32(r_xmm0, 0x55);
r_xmm0 = _mm_shufflehi_epi16(r_xmm0, 0xd8);
r_xmm3 = _mm_madd_epi16(r_xmm3, *((__m128i *)&pTab_i_04[16]));
r_xmm2 = _mm_shuffle_epi32(r_xmm0, 0xaa);
r_xmm0 = _mm_shuffle_epi32(r_xmm0, 0xff);
r_xmm2 = _mm_madd_epi16(r_xmm2, *((__m128i *)&pTab_i_04[8]));
r_xmm4 = _mm_shufflehi_epi16(r_xmm4, 0xd8);
r_xmm1 = _mm_add_epi32(r_xmm1, *((__m128i *)shortM128_round_inv_row));
r_xmm4 = _mm_shufflelo_epi16(r_xmm4, 0xd8);
r_xmm0 = _mm_madd_epi16(r_xmm0, *((__m128i *)&pTab_i_04[24]));
r_xmm5 = _mm_shuffle_epi32(r_xmm4, 0);
r_xmm6 = _mm_shuffle_epi32(r_xmm4, 0xaa);
r_xmm5 = _mm_madd_epi16(r_xmm5, *((__m128i *)&shortM128_tab_i_26[0]));
r_xmm1 = _mm_add_epi32(r_xmm1, r_xmm2);
r_xmm2 = r_xmm1;
r_xmm7 = _mm_shuffle_epi32(r_xmm4, 0x55);
r_xmm6 = _mm_madd_epi16(r_xmm6, *((__m128i *)&shortM128_tab_i_26[8]));
r_xmm0 = _mm_add_epi32(r_xmm0, r_xmm3);
r_xmm4 = _mm_shuffle_epi32(r_xmm4, 0xff);
r_xmm2 = _mm_sub_epi32(r_xmm2, r_xmm0);
r_xmm7 = _mm_madd_epi16(r_xmm7, *((__m128i *)&shortM128_tab_i_26[16]));
r_xmm0 = _mm_add_epi32(r_xmm0, r_xmm1);
r_xmm2 = _mm_srai_epi32(r_xmm2, 12);
r_xmm5 = _mm_add_epi32(r_xmm5, *((__m128i *)shortM128_round_inv_row));
r_xmm4 = _mm_madd_epi16(r_xmm4, *((__m128i *)&shortM128_tab_i_26[24]));
r_xmm5 = _mm_add_epi32(r_xmm5, r_xmm6);
r_xmm6 = r_xmm5;
r_xmm0 = _mm_srai_epi32(r_xmm0, 12);
r_xmm2 = _mm_shuffle_epi32(r_xmm2, 0x1b);
row4 = _mm_packs_epi32(r_xmm0, r_xmm2);
r_xmm4 = _mm_add_epi32(r_xmm4, r_xmm7);
r_xmm6 = _mm_sub_epi32(r_xmm6, r_xmm4);
r_xmm4 = _mm_add_epi32(r_xmm4, r_xmm5);
r_xmm6 = _mm_srai_epi32(r_xmm6, 12);
r_xmm4 = _mm_srai_epi32(r_xmm4, 12);
r_xmm6 = _mm_shuffle_epi32(r_xmm6, 0x1b);
row6 = _mm_packs_epi32(r_xmm4, r_xmm6);
// Row 4 and row 2
pTab_i_04 = shortM128_tab_i_35;
pTab_i_26 = shortM128_tab_i_17;
r_xmm0 = _mm_load_si128((__m128i *)(&pInput[3 * 8]));
r_xmm4 = _mm_load_si128((__m128i *)(&pInput[1 * 8]));
r_xmm0 = _mm_shufflelo_epi16(r_xmm0, 0xd8);
r_xmm1 = _mm_shuffle_epi32(r_xmm0, 0);
r_xmm1 = _mm_madd_epi16(r_xmm1, *((__m128i *)pTab_i_04));
r_xmm3 = _mm_shuffle_epi32(r_xmm0, 0x55);
r_xmm0 = _mm_shufflehi_epi16(r_xmm0, 0xd8);
r_xmm3 = _mm_madd_epi16(r_xmm3, *((__m128i *)&pTab_i_04[16]));
r_xmm2 = _mm_shuffle_epi32(r_xmm0, 0xaa);
r_xmm0 = _mm_shuffle_epi32(r_xmm0, 0xff);
r_xmm2 = _mm_madd_epi16(r_xmm2, *((__m128i *)&pTab_i_04[8]));
r_xmm4 = _mm_shufflehi_epi16(r_xmm4, 0xd8);
r_xmm1 = _mm_add_epi32(r_xmm1, *((__m128i *)shortM128_round_inv_row));
r_xmm4 = _mm_shufflelo_epi16(r_xmm4, 0xd8);
r_xmm0 = _mm_madd_epi16(r_xmm0, *((__m128i *)&pTab_i_04[24]));
r_xmm5 = _mm_shuffle_epi32(r_xmm4, 0);
r_xmm6 = _mm_shuffle_epi32(r_xmm4, 0xaa);
r_xmm5 = _mm_madd_epi16(r_xmm5, *((__m128i *)&pTab_i_26[0]));
r_xmm1 = _mm_add_epi32(r_xmm1, r_xmm2);
r_xmm2 = r_xmm1;
r_xmm7 = _mm_shuffle_epi32(r_xmm4, 0x55);
r_xmm6 = _mm_madd_epi16(r_xmm6, *((__m128i *)&pTab_i_26[8]));
r_xmm0 = _mm_add_epi32(r_xmm0, r_xmm3);
r_xmm4 = _mm_shuffle_epi32(r_xmm4, 0xff);
r_xmm2 = _mm_sub_epi32(r_xmm2, r_xmm0);
r_xmm7 = _mm_madd_epi16(r_xmm7, *((__m128i *)&pTab_i_26[16]));
r_xmm0 = _mm_add_epi32(r_xmm0, r_xmm1);
r_xmm2 = _mm_srai_epi32(r_xmm2, 12);
r_xmm5 = _mm_add_epi32(r_xmm5, *((__m128i *)shortM128_round_inv_row));
r_xmm4 = _mm_madd_epi16(r_xmm4, *((__m128i *)&pTab_i_26[24]));
r_xmm5 = _mm_add_epi32(r_xmm5, r_xmm6);
r_xmm6 = r_xmm5;
r_xmm0 = _mm_srai_epi32(r_xmm0, 12);
r_xmm2 = _mm_shuffle_epi32(r_xmm2, 0x1b);
row3 = _mm_packs_epi32(r_xmm0, r_xmm2);
r_xmm4 = _mm_add_epi32(r_xmm4, r_xmm7);
r_xmm6 = _mm_sub_epi32(r_xmm6, r_xmm4);
r_xmm4 = _mm_add_epi32(r_xmm4, r_xmm5);
r_xmm6 = _mm_srai_epi32(r_xmm6, 12);
r_xmm4 = _mm_srai_epi32(r_xmm4, 12);
r_xmm6 = _mm_shuffle_epi32(r_xmm6, 0x1b);
row1 = _mm_packs_epi32(r_xmm4, r_xmm6);
// Row 6 and row 8
r_xmm0 = _mm_load_si128((__m128i *)(&pInput[5 * 8]));
r_xmm4 = _mm_load_si128((__m128i *)(&pInput[7 * 8]));
r_xmm0 = _mm_shufflelo_epi16(r_xmm0, 0xd8);
r_xmm1 = _mm_shuffle_epi32(r_xmm0, 0);
r_xmm1 = _mm_madd_epi16(r_xmm1, *((__m128i *)pTab_i_04));
r_xmm3 = _mm_shuffle_epi32(r_xmm0, 0x55);
r_xmm0 = _mm_shufflehi_epi16(r_xmm0, 0xd8);
r_xmm3 = _mm_madd_epi16(r_xmm3, *((__m128i *)&pTab_i_04[16]));
r_xmm2 = _mm_shuffle_epi32(r_xmm0, 0xaa);
r_xmm0 = _mm_shuffle_epi32(r_xmm0, 0xff);
r_xmm2 = _mm_madd_epi16(r_xmm2, *((__m128i *)&pTab_i_04[8]));
r_xmm4 = _mm_shufflehi_epi16(r_xmm4, 0xd8);
r_xmm1 = _mm_add_epi32(r_xmm1, *((__m128i *)shortM128_round_inv_row));
r_xmm4 = _mm_shufflelo_epi16(r_xmm4, 0xd8);
r_xmm0 = _mm_madd_epi16(r_xmm0, *((__m128i *)&pTab_i_04[24]));
r_xmm5 = _mm_shuffle_epi32(r_xmm4, 0);
r_xmm6 = _mm_shuffle_epi32(r_xmm4, 0xaa);
r_xmm5 = _mm_madd_epi16(r_xmm5, *((__m128i *)&pTab_i_26[0]));
r_xmm1 = _mm_add_epi32(r_xmm1, r_xmm2);
r_xmm2 = r_xmm1;
r_xmm7 = _mm_shuffle_epi32(r_xmm4, 0x55);
r_xmm6 = _mm_madd_epi16(r_xmm6, *((__m128i *)&pTab_i_26[8]));
r_xmm0 = _mm_add_epi32(r_xmm0, r_xmm3);
r_xmm4 = _mm_shuffle_epi32(r_xmm4, 0xff);
r_xmm2 = _mm_sub_epi32(r_xmm2, r_xmm0);
r_xmm7 = _mm_madd_epi16(r_xmm7, *((__m128i *)&pTab_i_26[16]));
r_xmm0 = _mm_add_epi32(r_xmm0, r_xmm1);
r_xmm2 = _mm_srai_epi32(r_xmm2, 12);
r_xmm5 = _mm_add_epi32(r_xmm5, *((__m128i *)shortM128_round_inv_row));
r_xmm4 = _mm_madd_epi16(r_xmm4, *((__m128i *)&pTab_i_26[24]));
r_xmm5 = _mm_add_epi32(r_xmm5, r_xmm6);
r_xmm6 = r_xmm5;
r_xmm0 = _mm_srai_epi32(r_xmm0, 12);
r_xmm2 = _mm_shuffle_epi32(r_xmm2, 0x1b);
row5 = _mm_packs_epi32(r_xmm0, r_xmm2);
r_xmm4 = _mm_add_epi32(r_xmm4, r_xmm7);
r_xmm6 = _mm_sub_epi32(r_xmm6, r_xmm4);
r_xmm4 = _mm_add_epi32(r_xmm4, r_xmm5);
r_xmm6 = _mm_srai_epi32(r_xmm6, 12);
r_xmm4 = _mm_srai_epi32(r_xmm4, 12);
r_xmm6 = _mm_shuffle_epi32(r_xmm6, 0x1b);
row7 = _mm_packs_epi32(r_xmm4, r_xmm6);
r_xmm1 = _mm_load_si128((__m128i *)shortM128_tg_3_16);
r_xmm2 = row5;
r_xmm3 = row3;
r_xmm0 = _mm_mulhi_epi16(row5, r_xmm1);
r_xmm1 = _mm_mulhi_epi16(r_xmm1, r_xmm3);
r_xmm5 = _mm_load_si128((__m128i *)shortM128_tg_1_16);
r_xmm6 = row7;
r_xmm4 = _mm_mulhi_epi16(row7, r_xmm5);
r_xmm0 = _mm_adds_epi16(r_xmm0, r_xmm2);
r_xmm5 = _mm_mulhi_epi16(r_xmm5, row1);
r_xmm1 = _mm_adds_epi16(r_xmm1, r_xmm3);
r_xmm7 = row6;
r_xmm0 = _mm_adds_epi16(r_xmm0, r_xmm3);
r_xmm3 = _mm_load_si128((__m128i *)shortM128_tg_2_16);
r_xmm2 = _mm_subs_epi16(r_xmm2, r_xmm1);
r_xmm7 = _mm_mulhi_epi16(r_xmm7, r_xmm3);
r_xmm1 = r_xmm0;
r_xmm3 = _mm_mulhi_epi16(r_xmm3, row2);
r_xmm5 = _mm_subs_epi16(r_xmm5, r_xmm6);
r_xmm4 = _mm_adds_epi16(r_xmm4, row1);
r_xmm0 = _mm_adds_epi16(r_xmm0, r_xmm4);
r_xmm0 = _mm_adds_epi16(r_xmm0, *((__m128i *)shortM128_one_corr));
r_xmm4 = _mm_subs_epi16(r_xmm4, r_xmm1);
r_xmm6 = r_xmm5;
r_xmm5 = _mm_subs_epi16(r_xmm5, r_xmm2);
r_xmm5 = _mm_adds_epi16(r_xmm5, *((__m128i *)shortM128_one_corr));
r_xmm6 = _mm_adds_epi16(r_xmm6, r_xmm2);
// Intermediate results, needed later
__m128i temp3, temp7;
temp7 = r_xmm0;
r_xmm1 = r_xmm4;
r_xmm0 = _mm_load_si128((__m128i *)shortM128_cos_4_16);
r_xmm4 = _mm_adds_epi16(r_xmm4, r_xmm5);
r_xmm2 = _mm_load_si128((__m128i *)shortM128_cos_4_16);
r_xmm2 = _mm_mulhi_epi16(r_xmm2, r_xmm4);
// Intermediate results, needed later
temp3 = r_xmm6;
r_xmm1 = _mm_subs_epi16(r_xmm1, r_xmm5);
r_xmm7 = _mm_adds_epi16(r_xmm7, row2);
r_xmm3 = _mm_subs_epi16(r_xmm3, row6);
r_xmm6 = row0;
r_xmm0 = _mm_mulhi_epi16(r_xmm0, r_xmm1);
r_xmm5 = row4;
r_xmm5 = _mm_adds_epi16(r_xmm5, r_xmm6);
r_xmm6 = _mm_subs_epi16(r_xmm6, row4);
r_xmm4 = _mm_adds_epi16(r_xmm4, r_xmm2);
r_xmm4 = _mm_or_si128(r_xmm4, *((__m128i *)shortM128_one_corr));
r_xmm0 = _mm_adds_epi16(r_xmm0, r_xmm1);
r_xmm0 = _mm_or_si128(r_xmm0, *((__m128i *)shortM128_one_corr));
r_xmm2 = r_xmm5;
r_xmm5 = _mm_adds_epi16(r_xmm5, r_xmm7);
r_xmm1 = r_xmm6;
r_xmm5 = _mm_adds_epi16(r_xmm5, *((__m128i *)shortM128_round_inv_col));
r_xmm2 = _mm_subs_epi16(r_xmm2, r_xmm7);
r_xmm7 = temp7;
r_xmm6 = _mm_adds_epi16(r_xmm6, r_xmm3);
r_xmm6 = _mm_adds_epi16(r_xmm6, *((__m128i *)shortM128_round_inv_col));
r_xmm7 = _mm_adds_epi16(r_xmm7, r_xmm5);
r_xmm7 = _mm_srai_epi16(r_xmm7, SHIFT_INV_COL);
r_xmm1 = _mm_subs_epi16(r_xmm1, r_xmm3);
r_xmm1 = _mm_adds_epi16(r_xmm1, *((__m128i *)shortM128_round_inv_corr));
r_xmm3 = r_xmm6;
r_xmm2 = _mm_adds_epi16(r_xmm2, *((__m128i *)shortM128_round_inv_corr));
r_xmm6 = _mm_adds_epi16(r_xmm6, r_xmm4);
// Store results for row 0
//_mm_store_si128((__m128i *) pOutput, r_xmm7);
__m128i r0 = r_xmm7;
r_xmm6 = _mm_srai_epi16(r_xmm6, SHIFT_INV_COL);
r_xmm7 = r_xmm1;
r_xmm1 = _mm_adds_epi16(r_xmm1, r_xmm0);
// Store results for row 1
//_mm_store_si128((__m128i *) (&pOutput[1*8]), r_xmm6);
__m128i r1 = r_xmm6;
r_xmm1 = _mm_srai_epi16(r_xmm1, SHIFT_INV_COL);
r_xmm6 = temp3;
r_xmm7 = _mm_subs_epi16(r_xmm7, r_xmm0);
r_xmm7 = _mm_srai_epi16(r_xmm7, SHIFT_INV_COL);
// Store results for row 2
//_mm_store_si128((__m128i *) (&pOutput[2*8]), r_xmm1);
__m128i r2 = r_xmm1;
r_xmm5 = _mm_subs_epi16(r_xmm5, temp7);
r_xmm5 = _mm_srai_epi16(r_xmm5, SHIFT_INV_COL);
// Store results for row 7
//_mm_store_si128((__m128i *) (&pOutput[7*8]), r_xmm5);
__m128i r7 = r_xmm5;
r_xmm3 = _mm_subs_epi16(r_xmm3, r_xmm4);
r_xmm6 = _mm_adds_epi16(r_xmm6, r_xmm2);
r_xmm2 = _mm_subs_epi16(r_xmm2, temp3);
r_xmm6 = _mm_srai_epi16(r_xmm6, SHIFT_INV_COL);
r_xmm2 = _mm_srai_epi16(r_xmm2, SHIFT_INV_COL);
// Store results for row 3
//_mm_store_si128((__m128i *) (&pOutput[3*8]), r_xmm6);
__m128i r3 = r_xmm6;
r_xmm3 = _mm_srai_epi16(r_xmm3, SHIFT_INV_COL);
// Store results for rows 4, 5, and 6
//_mm_store_si128((__m128i *) (&pOutput[4*8]), r_xmm2);
//_mm_store_si128((__m128i *) (&pOutput[5*8]), r_xmm7);
//_mm_store_si128((__m128i *) (&pOutput[6*8]), r_xmm3);
__m128i r4 = r_xmm2;
__m128i r5 = r_xmm7;
__m128i r6 = r_xmm3;
r0 = _mm_add_epi16(*(const __m128i *)shortM128_128, r0);
r1 = _mm_add_epi16(*(const __m128i *)shortM128_128, r1);
r2 = _mm_add_epi16(*(const __m128i *)shortM128_128, r2);
r3 = _mm_add_epi16(*(const __m128i *)shortM128_128, r3);
r4 = _mm_add_epi16(*(const __m128i *)shortM128_128, r4);
r5 = _mm_add_epi16(*(const __m128i *)shortM128_128, r5);
r6 = _mm_add_epi16(*(const __m128i *)shortM128_128, r6);
r7 = _mm_add_epi16(*(const __m128i *)shortM128_128, r7);
((__m128i *)pOutputUB)[0] = _mm_packus_epi16(r0, r1);
((__m128i *)pOutputUB)[1] = _mm_packus_epi16(r2, r3);
((__m128i *)pOutputUB)[2] = _mm_packus_epi16(r4, r5);
((__m128i *)pOutputUB)[3] = _mm_packus_epi16(r6, r7);
}
+186
View File
@@ -0,0 +1,186 @@
// jpge.h - C++ class for JPEG compression.
// Public Domain or Apache 2.0, Richard Geldreich <richgel99@gmail.com>
// Alex Evans: Added RGBA support, linear memory allocator.
#ifndef JPEG_ENCODER_H
#define JPEG_ENCODER_H
namespace jpge {
typedef unsigned char uint8;
typedef signed short int16;
typedef signed int int32;
typedef unsigned short uint16;
typedef unsigned int uint32;
typedef unsigned int uint;
// JPEG chroma subsampling factors. Y_ONLY (grayscale images) and H2V2 (color
// images) are the most common.
enum subsampling_t { Y_ONLY = 0, H1V1 = 1, H2V1 = 2, H2V2 = 3 };
// JPEG compression parameters structure.
struct params {
inline params()
: m_quality(85), m_subsampling(H2V2), m_no_chroma_discrim_flag(false),
m_two_pass_flag(false), m_use_std_tables(false) {}
inline bool check() const {
if ((m_quality < 1) || (m_quality > 100))
return false;
if ((uint)m_subsampling > (uint)H2V2)
return false;
return true;
}
// Quality: 1-100, higher is better. Typical values are around 50-95.
int m_quality;
// m_subsampling:
// 0 = Y (grayscale) only
// 1 = YCbCr, no subsampling (H1V1, YCbCr 1x1x1, 3 blocks per MCU)
// 2 = YCbCr, H2V1 subsampling (YCbCr 2x1x1, 4 blocks per MCU)
// 3 = YCbCr, H2V2 subsampling (YCbCr 4x1x1, 6 blocks per MCU-- very common)
subsampling_t m_subsampling;
// Disables CbCr discrimination - only intended for testing.
// If true, the Y quantization table is also used for the CbCr channels.
bool m_no_chroma_discrim_flag;
bool m_two_pass_flag;
// By default we use the same quantization tables as mozjpeg's default.
// Set to true to use the traditional tables from JPEG Annex K.
bool m_use_std_tables;
};
// Writes JPEG image to a file.
// num_channels must be 1 (Y) or 3 (RGB), image pitch must be
// width*num_channels.
bool compress_image_to_jpeg_file(const char *pFilename, int width, int height,
int num_channels, const uint8 *pImage_data,
const params &comp_params = params());
// Writes JPEG image to memory buffer.
// On entry, buf_size is the size of the output buffer pointed at by pBuf, which
// should be at least ~1024 bytes. If return value is true, buf_size will be set
// to the size of the compressed data.
bool compress_image_to_jpeg_file_in_memory(
void *pBuf, int &buf_size, int width, int height, int num_channels,
const uint8 *pImage_data, const params &comp_params = params());
// Output stream abstract class - used by the jpeg_encoder class to write to the
// output stream. put_buf() is generally called with len==JPGE_OUT_BUF_SIZE
// bytes, but for headers it'll be called with smaller amounts.
class output_stream {
public:
virtual ~output_stream(){};
virtual bool put_buf(const void *Pbuf, int len) = 0;
template <class T> inline bool put_obj(const T &obj) {
return put_buf(&obj, sizeof(T));
}
};
// Lower level jpeg_encoder class - useful if more control is needed than the
// above helper functions.
class jpeg_encoder {
public:
jpeg_encoder();
~jpeg_encoder();
// Initializes the compressor.
// pStream: The stream object to use for writing compressed data.
// params - Compression parameters structure, defined above.
// width, height - Image dimensions.
// channels - May be 1, or 3. 1 indicates grayscale, 3 indicates RGB source
// data. Returns false on out of memory or if a stream write fails.
bool init(output_stream *pStream, int width, int height, int src_channels,
const params &comp_params = params());
const params &get_params() const { return m_params; }
// Deinitializes the compressor, freeing any allocated memory. May be called
// at any time.
void deinit();
uint get_total_passes() const { return m_params.m_two_pass_flag ? 2 : 1; }
inline uint get_cur_pass() { return m_pass_num; }
// Call this method with each source scanline.
// width * src_channels bytes per scanline is expected (RGB or Y format).
// You must call with NULL after all scanlines are processed to finish
// compression. Returns false on out of memory or if a stream write fails.
bool process_scanline(const void *pScanline);
private:
jpeg_encoder(const jpeg_encoder &);
jpeg_encoder &operator=(const jpeg_encoder &);
typedef int32 sample_array_t;
output_stream *m_pStream;
params m_params;
uint8 m_num_components;
uint8 m_comp_h_samp[3], m_comp_v_samp[3];
int m_image_x, m_image_y, m_image_bpp, m_image_bpl;
int m_image_x_mcu, m_image_y_mcu;
int m_image_bpl_xlt, m_image_bpl_mcu;
int m_mcus_per_row;
int m_mcu_x, m_mcu_y;
uint8 *m_mcu_lines[16];
uint8 m_mcu_y_ofs;
sample_array_t m_sample_array[64];
int16 m_coefficient_array[64];
int32 m_quantization_tables[2][64];
uint m_huff_codes[4][256];
uint8 m_huff_code_sizes[4][256];
uint8 m_huff_bits[4][17];
uint8 m_huff_val[4][256];
uint32 m_huff_count[4][256];
int m_last_dc_val[3];
enum { JPGE_OUT_BUF_SIZE = 2048 };
uint8 m_out_buf[JPGE_OUT_BUF_SIZE];
uint8 *m_pOut_buf;
uint m_out_buf_left;
uint32 m_bit_buffer;
uint m_bits_in;
uint8 m_pass_num;
bool m_all_stream_writes_succeeded;
void optimize_huffman_table(int table_num, int table_len);
void emit_byte(uint8 i);
void emit_word(uint i);
void emit_marker(int marker);
void emit_jfif_app0();
void emit_dqt();
void emit_sof();
void emit_dht(uint8 *bits, uint8 *val, int index, bool ac_flag);
void emit_dhts();
void emit_sos();
void emit_markers();
void compute_huffman_table(uint *codes, uint8 *code_sizes, uint8 *bits,
uint8 *val);
void compute_quant_table(int32 *dst, int16 *src);
void adjust_quant_table(int32 *dst, int32 *src);
void first_pass_init();
bool second_pass_init();
bool jpg_open(int p_x_res, int p_y_res, int src_channels);
void load_block_8_8_grey(int x);
void load_block_8_8(int x, int y, int c);
void load_block_16_8(int x, int c);
void load_block_16_8_8(int x, int c);
void load_quantized_coefficients(int component_num);
void flush_output_buffer();
void put_bits(uint bits, uint len);
void code_coefficients_pass_one(int component_num);
void code_coefficients_pass_two(int component_num);
void code_block(int component_num);
void process_mcu_row();
bool terminate_pass_one();
bool terminate_pass_two();
bool process_end_of_image();
void load_mcu(const void *src);
void clear();
void init();
};
} // namespace jpge
#endif // JPEG_ENCODER
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+222
View File
@@ -0,0 +1,222 @@
#pragma once
#include <cstdint>
#include <fstream>
#include <iostream>
#include <memory.h>
#include <memory>
#include <renderd7/external/jpgd.h>
#include <renderd7/external/jpge.h>
#include <sstream>
#include <vector>
struct NVID_Header {
char magic[4]; // Magic
int framerate; // Only Up to 60
int width; // Width
int height; // Height
uint32_t framecount; // Count of Frames
};
struct NVID_Frame {
char magic[4]; // Magic
uint32_t framesize; // Size of Frame
};
struct NVID_Image {
int framenum; // Register of Frame
int w; // Width of Frame
int h; // Height of Frame
int bpp; // bpp of Frame
void *pBuf; // Buffer
};
inline void CreateHeader(NVID_Header &header) {
header.magic[0] = 'N';
header.magic[1] = 'V';
header.magic[2] = 'I';
header.magic[3] = 'D';
}
inline void CreateFrame(NVID_Frame &frame) {
frame.magic[0] = 'N';
frame.magic[1] = 'F';
frame.magic[2] = 'R';
frame.magic[3] = 'M';
}
inline bool CheckHeader(NVID_Header &header) {
if (header.magic[0] == 'N' && header.magic[1] == 'V' &&
header.magic[2] == 'I' && header.magic[3] == 'D')
return true;
return false;
}
inline bool CheckFrame(NVID_Frame &frame) {
if (frame.magic[0] == 'N' && frame.magic[1] == 'F' && frame.magic[2] == 'R' &&
frame.magic[3] == 'M')
return true;
return false;
}
inline std::vector<std::unique_ptr<NVID_Image>>
LoadNVID(const std::string &path) {
std::vector<std::unique_ptr<NVID_Image>> res;
std::ifstream nvid_file(path, std::ios::binary | std::ios::in);
if (!nvid_file) {
std::cerr << "Failed to open NVID file: " << path << std::endl;
return res;
}
NVID_Header header;
nvid_file.read(reinterpret_cast<char *>(&header), sizeof(header));
if (!CheckHeader(header)) {
std::cerr << "Invalid NVID header" << std::endl;
return res;
}
for (int i = 0; i < (int)header.framecount; i++) {
NVID_Frame frame;
nvid_file.read(reinterpret_cast<char *>(&frame), sizeof(frame));
if (!CheckFrame(frame)) {
std::cerr << "Invalid NVID frame" << std::endl;
return res;
}
std::vector<uint8_t> compressed_data(frame.framesize);
nvid_file.read(reinterpret_cast<char *>(compressed_data.data()),
compressed_data.size());
int width, height, components;
unsigned char *decompressed_data = jpgd::decompress_jpeg_image_from_memory(
compressed_data.data(), compressed_data.size(), &width, &height,
&components, 3);
if (!decompressed_data) {
std::cerr << "Failed to decompress JPEG data" << std::endl;
return res;
}
auto image = std::make_unique<NVID_Image>();
image->bpp = components;
image->w = width;
image->h = height;
image->framenum = i;
image->pBuf = decompressed_data;
res.push_back(std::move(image));
}
return res;
}
inline std::vector<std::unique_ptr<NVID_Image>> LoadMemNVID(const void *data,
size_t size) {
std::vector<std::unique_ptr<NVID_Image>> res;
std::istringstream nvid_stream(
std::string(reinterpret_cast<const char *>(data), size));
NVID_Header header;
nvid_stream.read(reinterpret_cast<char *>(&header), sizeof(header));
if (!CheckHeader(header)) {
std::cerr << "Invalid NVID header" << std::endl;
return res;
}
for (int i = 0; i < (int)header.framecount; i++) {
NVID_Frame frame;
nvid_stream.read(reinterpret_cast<char *>(&frame), sizeof(frame));
if (!CheckFrame(frame)) {
std::cerr << "Invalid NVID frame" << std::endl;
return res;
}
std::vector<uint8_t> compressed_data(frame.framesize);
nvid_stream.read(reinterpret_cast<char *>(compressed_data.data()),
compressed_data.size());
int width, height, components;
unsigned char *decompressed_data = jpgd::decompress_jpeg_image_from_memory(
compressed_data.data(), compressed_data.size(), &width, &height,
&components, 3);
if (!decompressed_data) {
std::cerr << "Failed to decompress JPEG data" << std::endl;
return res;
}
auto image = std::make_unique<NVID_Image>();
image->bpp = components;
image->w = width;
image->h = height;
image->framenum = i;
image->pBuf = decompressed_data;
res.push_back(std::move(image));
}
return res;
}
class NVID_Stream {
public:
NVID_Stream(const std::string &path)
: file_(path, std::ios::binary | std::ios::in) {
if (!file_) {
std::cout << "Failed to open NVID file: " << path << std::endl;
return;
} else {
file_.read(reinterpret_cast<char *>(&header_), sizeof(header_));
if (!CheckHeader(header_)) {
std::cout << "Invalid NVID header" << std::endl;
return;
}
}
}
NVID_Stream(const void *data, std::size_t size) {
if (!data || size < sizeof(header_)) {
std::cout << "Invalid NVID data" << std::endl;
return;
} else {
memcpy(&header_, data, sizeof(header_));
if (!CheckHeader(header_)) {
std::cout << "Invalid NVID header" << std::endl;
return;
}
}
}
~NVID_Stream() { file_.close(); }
bool ReadNext(NVID_Image &image) {
if (!file_) {
return false;
}
NVID_Frame frame;
file_.read(reinterpret_cast<char *>(&frame), sizeof(frame));
if (!CheckFrame(frame)) {
std::cout << "Invalid NVID frame" << std::endl;
return false;
}
std::vector<uint8_t> compressed_data(frame.framesize);
file_.read(reinterpret_cast<char *>(compressed_data.data()),
compressed_data.size());
int width, height, components;
unsigned char *decompressed_data = jpgd::decompress_jpeg_image_from_memory(
compressed_data.data(), compressed_data.size(), &width, &height,
&components, 3);
if (!decompressed_data) {
std::cout << "Failed to decompress JPEG data" << std::endl;
return false;
}
image.bpp = components;
image.w = width;
image.h = height;
image.framenum = current_frame_++;
image.pBuf = decompressed_data;
return true;
}
private:
std::ifstream file_;
NVID_Header header_;
int current_frame_ = 0;
};
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+545
View File
@@ -0,0 +1,545 @@
#ifndef INI_INI_H_
#define INI_INI_H_
#include <algorithm>
#include <cctype>
#include <fstream>
#include <memory>
#include <sstream>
#include <string>
#include <sys/stat.h>
#include <unordered_map>
#include <utility>
#include <vector>
namespace INI {
namespace INIStringUtil {
const char *const whitespaceDelimiters = " \t\n\r\f\v";
inline void trim(std::string &str) {
str.erase(str.find_last_not_of(whitespaceDelimiters) + 1);
str.erase(0, str.find_first_not_of(whitespaceDelimiters));
}
#ifndef INI_CASE_SENSITIVE
inline void toLower(std::string &str) {
std::transform(str.begin(), str.end(), str.begin(), [](const char c) {
return static_cast<const char>(std::tolower(c));
});
}
#endif
inline void replace(std::string &str, std::string const &a,
std::string const &b) {
if (!a.empty()) {
std::size_t pos = 0;
while ((pos = str.find(a, pos)) != std::string::npos) {
str.replace(pos, a.size(), b);
pos += b.size();
}
}
}
#ifdef _WIN32
const char *const endl = "\r\n";
#else
const char *const endl = "\n";
#endif
}; // namespace INIStringUtil
template <typename T> class INIMap {
private:
using T_DataIndexMap = std::unordered_map<std::string, std::size_t>;
using T_DataItem = std::pair<std::string, T>;
using T_DataContainer = std::vector<T_DataItem>;
using T_MultiArgs = typename std::vector<std::pair<std::string, T>>;
T_DataIndexMap dataIndexMap;
T_DataContainer data;
inline std::size_t setEmpty(std::string &key) {
std::size_t index = data.size();
dataIndexMap[key] = index;
data.emplace_back(key, T());
return index;
}
public:
using const_iterator = typename T_DataContainer::const_iterator;
INIMap() {}
INIMap(INIMap const &other) {
std::size_t data_size = other.data.size();
for (std::size_t i = 0; i < data_size; ++i) {
auto const &key = other.data[i].first;
auto const &obj = other.data[i].second;
data.emplace_back(key, obj);
}
dataIndexMap = T_DataIndexMap(other.dataIndexMap);
}
T &operator[](std::string key) {
INIStringUtil::trim(key);
#ifndef INI_CASE_SENSITIVE
INIStringUtil::toLower(key);
#endif
auto it = dataIndexMap.find(key);
bool hasIt = (it != dataIndexMap.end());
std::size_t index = (hasIt) ? it->second : setEmpty(key);
return data[index].second;
}
T get(std::string key) const {
INIStringUtil::trim(key);
#ifndef INI_CASE_SENSITIVE
INIStringUtil::toLower(key);
#endif
auto it = dataIndexMap.find(key);
if (it == dataIndexMap.end()) {
return T();
}
return T(data[it->second].second);
}
bool has(std::string key) const {
INIStringUtil::trim(key);
#ifndef INI_CASE_SENSITIVE
INIStringUtil::toLower(key);
#endif
return (dataIndexMap.count(key) == 1);
}
void set(std::string key, T obj) {
INIStringUtil::trim(key);
#ifndef INI_CASE_SENSITIVE
INIStringUtil::toLower(key);
#endif
auto it = dataIndexMap.find(key);
if (it != dataIndexMap.end()) {
data[it->second].second = obj;
} else {
dataIndexMap[key] = data.size();
data.emplace_back(key, obj);
}
}
void set(T_MultiArgs const &multiArgs) {
for (auto const &it : multiArgs) {
auto const &key = it.first;
auto const &obj = it.second;
set(key, obj);
}
}
bool remove(std::string key) {
INIStringUtil::trim(key);
#ifndef INI_CASE_SENSITIVE
INIStringUtil::toLower(key);
#endif
auto it = dataIndexMap.find(key);
if (it != dataIndexMap.end()) {
std::size_t index = it->second;
data.erase(data.begin() + index);
dataIndexMap.erase(it);
for (auto &it2 : dataIndexMap) {
auto &vi = it2.second;
if (vi > index) {
vi--;
}
}
return true;
}
return false;
}
void clear() {
data.clear();
dataIndexMap.clear();
}
std::size_t size() const { return data.size(); }
const_iterator begin() const { return data.begin(); }
const_iterator end() const { return data.end(); }
};
using INIStructure = INIMap<INIMap<std::string>>;
namespace INIParser {
using T_ParseValues = std::pair<std::string, std::string>;
enum class PDataType : char {
PDATA_NONE,
PDATA_COMMENT,
PDATA_SECTION,
PDATA_KEYVALUE,
PDATA_UNKNOWN
};
inline PDataType parseLine(std::string line, T_ParseValues &parseData) {
parseData.first.clear();
parseData.second.clear();
INIStringUtil::trim(line);
if (line.empty()) {
return PDataType::PDATA_NONE;
}
char firstCharacter = line[0];
if (firstCharacter == ';') {
return PDataType::PDATA_COMMENT;
}
if (firstCharacter == '[') {
auto commentAt = line.find_first_of(';');
if (commentAt != std::string::npos) {
line = line.substr(0, commentAt);
}
auto closingBracketAt = line.find_last_of(']');
if (closingBracketAt != std::string::npos) {
auto section = line.substr(1, closingBracketAt - 1);
INIStringUtil::trim(section);
parseData.first = section;
return PDataType::PDATA_SECTION;
}
}
auto lineNorm = line;
INIStringUtil::replace(lineNorm, "\\=", " ");
auto equalsAt = lineNorm.find_first_of('=');
if (equalsAt != std::string::npos) {
auto key = line.substr(0, equalsAt);
INIStringUtil::trim(key);
INIStringUtil::replace(key, "\\=", "=");
auto value = line.substr(equalsAt + 1);
INIStringUtil::trim(value);
parseData.first = key;
parseData.second = value;
return PDataType::PDATA_KEYVALUE;
}
return PDataType::PDATA_UNKNOWN;
}
}; // namespace INIParser
class INIReader {
public:
using T_LineData = std::vector<std::string>;
using T_LineDataPtr = std::shared_ptr<T_LineData>;
private:
std::ifstream fileReadStream;
T_LineDataPtr lineData;
T_LineData readFile() {
std::string fileContents;
fileReadStream.seekg(0, std::ios::end);
fileContents.resize(fileReadStream.tellg());
fileReadStream.seekg(0, std::ios::beg);
std::size_t fileSize = fileContents.size();
fileReadStream.read(&fileContents[0], fileSize);
fileReadStream.close();
T_LineData output;
if (fileSize == 0) {
return output;
}
std::string buffer;
buffer.reserve(50);
for (std::size_t i = 0; i < fileSize; ++i) {
char &c = fileContents[i];
if (c == '\n') {
output.emplace_back(buffer);
buffer.clear();
continue;
}
if (c != '\0' && c != '\r') {
buffer += c;
}
}
output.emplace_back(buffer);
return output;
}
public:
INIReader(std::string const &filename, bool keepLineData = false) {
fileReadStream.open(filename, std::ios::in | std::ios::binary);
if (keepLineData) {
lineData = std::make_shared<T_LineData>();
}
}
~INIReader() {}
bool operator>>(INIStructure &data) {
if (!fileReadStream.is_open()) {
return false;
}
T_LineData fileLines = readFile();
std::string section;
bool inSection = false;
INIParser::T_ParseValues parseData;
for (auto const &line : fileLines) {
auto parseResult = INIParser::parseLine(line, parseData);
if (parseResult == INIParser::PDataType::PDATA_SECTION) {
inSection = true;
data[section = parseData.first];
} else if (inSection &&
parseResult == INIParser::PDataType::PDATA_KEYVALUE) {
auto const &key = parseData.first;
auto const &value = parseData.second;
data[section][key] = value;
}
if (lineData && parseResult != INIParser::PDataType::PDATA_UNKNOWN) {
if (parseResult == INIParser::PDataType::PDATA_KEYVALUE && !inSection) {
continue;
}
lineData->emplace_back(line);
}
}
return true;
}
T_LineDataPtr getLines() { return lineData; }
};
class INIGenerator {
private:
std::ofstream fileWriteStream;
public:
bool prettyPrint = false;
INIGenerator(std::string const &filename) {
fileWriteStream.open(filename, std::ios::out | std::ios::binary);
}
~INIGenerator() {}
bool operator<<(INIStructure const &data) {
if (!fileWriteStream.is_open()) {
return false;
}
if (!data.size()) {
return true;
}
auto it = data.begin();
for (;;) {
auto const &section = it->first;
auto const &collection = it->second;
fileWriteStream << "[" << section << "]";
if (collection.size()) {
fileWriteStream << INIStringUtil::endl;
auto it2 = collection.begin();
for (;;) {
auto key = it2->first;
INIStringUtil::replace(key, "=", "\\=");
auto value = it2->second;
INIStringUtil::trim(value);
fileWriteStream << key << ((prettyPrint) ? " = " : "=") << value;
if (++it2 == collection.end()) {
break;
}
fileWriteStream << INIStringUtil::endl;
}
}
if (++it == data.end()) {
break;
}
fileWriteStream << INIStringUtil::endl;
if (prettyPrint) {
fileWriteStream << INIStringUtil::endl;
}
}
return true;
}
};
class INIWriter {
private:
using T_LineData = std::vector<std::string>;
using T_LineDataPtr = std::shared_ptr<T_LineData>;
std::string filename;
T_LineData getLazyOutput(T_LineDataPtr const &lineData, INIStructure &data,
INIStructure &original) {
T_LineData output;
INIParser::T_ParseValues parseData;
std::string sectionCurrent;
bool parsingSection = false;
bool continueToNextSection = false;
bool discardNextEmpty = false;
bool writeNewKeys = false;
std::size_t lastKeyLine = 0;
for (auto line = lineData->begin(); line != lineData->end(); ++line) {
if (!writeNewKeys) {
auto parseResult = INIParser::parseLine(*line, parseData);
if (parseResult == INIParser::PDataType::PDATA_SECTION) {
if (parsingSection) {
writeNewKeys = true;
parsingSection = false;
--line;
continue;
}
sectionCurrent = parseData.first;
if (data.has(sectionCurrent)) {
parsingSection = true;
continueToNextSection = false;
discardNextEmpty = false;
output.emplace_back(*line);
lastKeyLine = output.size();
} else {
continueToNextSection = true;
discardNextEmpty = true;
continue;
}
} else if (parseResult == INIParser::PDataType::PDATA_KEYVALUE) {
if (continueToNextSection) {
continue;
}
if (data.has(sectionCurrent)) {
auto &collection = data[sectionCurrent];
auto const &key = parseData.first;
auto const &value = parseData.second;
if (collection.has(key)) {
auto outputValue = collection[key];
if (value == outputValue) {
output.emplace_back(*line);
} else {
INIStringUtil::trim(outputValue);
auto lineNorm = *line;
INIStringUtil::replace(lineNorm, "\\=", " ");
auto equalsAt = lineNorm.find_first_of('=');
auto valueAt = lineNorm.find_first_not_of(
INIStringUtil::whitespaceDelimiters, equalsAt + 1);
std::string outputLine = line->substr(0, valueAt);
if (prettyPrint && equalsAt + 1 == valueAt) {
outputLine += " ";
}
outputLine += outputValue;
output.emplace_back(outputLine);
}
lastKeyLine = output.size();
}
}
} else {
if (discardNextEmpty && line->empty()) {
discardNextEmpty = false;
} else if (parseResult != INIParser::PDataType::PDATA_UNKNOWN) {
output.emplace_back(*line);
}
}
}
if (writeNewKeys || std::next(line) == lineData->end()) {
T_LineData linesToAdd;
if (data.has(sectionCurrent) && original.has(sectionCurrent)) {
auto const &collection = data[sectionCurrent];
auto const &collectionOriginal = original[sectionCurrent];
for (auto const &it : collection) {
auto key = it.first;
if (collectionOriginal.has(key)) {
continue;
}
auto value = it.second;
INIStringUtil::replace(key, "=", "\\=");
INIStringUtil::trim(value);
linesToAdd.emplace_back(key + ((prettyPrint) ? " = " : "=") +
value);
}
}
if (!linesToAdd.empty()) {
output.insert(output.begin() + lastKeyLine, linesToAdd.begin(),
linesToAdd.end());
}
if (writeNewKeys) {
writeNewKeys = false;
--line;
}
}
}
for (auto const &it : data) {
auto const &section = it.first;
if (original.has(section)) {
continue;
}
if (prettyPrint && output.size() > 0 && !output.back().empty()) {
output.emplace_back();
}
output.emplace_back("[" + section + "]");
auto const &collection = it.second;
for (auto const &it2 : collection) {
auto key = it2.first;
auto value = it2.second;
INIStringUtil::replace(key, "=", "\\=");
INIStringUtil::trim(value);
output.emplace_back(key + ((prettyPrint) ? " = " : "=") + value);
}
}
return output;
}
public:
bool prettyPrint = false;
INIWriter(std::string const &filename) : filename(filename) {}
~INIWriter() {}
bool operator<<(INIStructure &data) {
struct stat buf;
bool fileExists = (stat(filename.c_str(), &buf) == 0);
if (!fileExists) {
INIGenerator generator(filename);
generator.prettyPrint = prettyPrint;
return generator << data;
}
INIStructure originalData;
T_LineDataPtr lineData;
bool readSuccess = false;
{
INIReader reader(filename, true);
if ((readSuccess = reader >> originalData)) {
lineData = reader.getLines();
}
}
if (!readSuccess) {
return false;
}
T_LineData output = getLazyOutput(lineData, data, originalData);
std::ofstream fileWriteStream(filename, std::ios::out | std::ios::binary);
if (fileWriteStream.is_open()) {
if (output.size()) {
auto line = output.begin();
for (;;) {
fileWriteStream << *line;
if (++line == output.end()) {
break;
}
fileWriteStream << INIStringUtil::endl;
}
}
return true;
}
return false;
}
};
class INIFile {
private:
std::string filename;
public:
INIFile(std::string const &filename) : filename(filename) {}
~INIFile() {}
bool read(INIStructure &data) const {
if (data.size()) {
data.clear();
}
if (filename.empty()) {
return false;
}
INIReader reader(filename);
return reader >> data;
}
bool generate(INIStructure const &data, bool pretty = false) const {
if (filename.empty()) {
return false;
}
INIGenerator generator(filename);
generator.prettyPrint = pretty;
return generator << data;
}
bool write(INIStructure &data, bool pretty = false) const {
if (filename.empty()) {
return false;
}
INIWriter writer(filename);
writer.prettyPrint = pretty;
return writer << data;
}
};
} // namespace INI
#endif
+18
View File
@@ -0,0 +1,18 @@
#pragma once
#include <renderd7/external/json.hpp>
#include <string>
namespace RenderD7 {
namespace Lang {
/// @brief Get 3ds System lang! [en] by default
/// @return Sytemlang as string
std::string getSys();
/// @brief Get The Translation String
/// @param key Key of Translation
/// @return The Translated String
std::string get(const std::string &key);
/// @brief Load A Language json
/// @param lang The Language Key [en], [de], etc, or getSys()
void load(const std::string &lang);
} // namespace Lang
} // namespace RenderD7
+33
View File
@@ -0,0 +1,33 @@
#pragma once
#include <fstream>
#include <stdarg.h>
#include <string>
#include <time.h>
#include <unistd.h>
/// @brief Log Class
class Log {
public:
/// @brief Constructor
Log();
/// @brief Deconstructor
~Log();
/// @brief Init the Logger
/// @param filename Filename[_data_time.log]
void Init(const char *filename);
/// @brief Write a String to the File
/// @param debug_text string
void Write(std::string debug_text);
/// @brief Get the Date
/// @return Date as string fmt[data_time]
std::string logDate(void);
/// @brief Format a string like sprintf
/// @param fmt_str the string wich defines the fmt
/// @param ... Additional Data
/// @return Formatted String
std::string format(const std::string &fmt_str, ...);
private:
/// \param filename the name of the logfile
std::string filename;
};
@@ -0,0 +1,5 @@
#pragma once
#include <cstddef>
extern unsigned char npi_intro[];
extern size_t npi_intro_size;
+118
View File
@@ -0,0 +1,118 @@
#pragma once
#include <tuple>
namespace RenderD7 {
class Parameter {
private:
using id = size_t;
template <typename T> struct type {
static void id() {}
};
template <typename T> static id type_id() {
return reinterpret_cast<id>(&type<T>::id);
}
template <typename T> using decay = typename std::decay<T>::type;
template <typename T>
using none =
typename std::enable_if<!std::is_same<Parameter, T>::value>::type;
struct base {
virtual ~base() {}
virtual bool is(id) const = 0;
virtual base *copy() const = 0;
} *p = nullptr;
template <typename T> struct data : base, std::tuple<T> {
using std::tuple<T>::tuple;
T &get() & { return std::get<0>(*this); }
T const &get() const & { return std::get<0>(*this); }
bool is(id i) const override { return i == type_id<T>(); }
base *copy() const override { return new data{get()}; }
};
template <typename T> T &stat() { return static_cast<data<T> &>(*p).get(); }
template <typename T> T const &stat() const {
return static_cast<data<T> const &>(*p).get();
}
template <typename T> T &dyn() { return dynamic_cast<data<T> &>(*p).get(); }
template <typename T> T const &dyn() const {
return dynamic_cast<data<T> const &>(*p).get();
}
public:
/**
* @brief Default constructor
*/
Parameter() {}
/**
* @brief Destructs the Parameter
*/
~Parameter() { delete p; }
/**
* @brief Copy constructor
* @param s The Parameter to copy
*/
Parameter(Parameter &&s) : p{s.p} { s.p = nullptr; }
/**
* @brief Const copy constructor
* @param s The Parameter to copy
*/
Parameter(Parameter const &s) : p{s.p->copy()} {}
/**
* @brief Initializes the Parameter with the given value
* @param x The value to initialize the Parameter with
*/
template <typename T, typename U = decay<T>, typename = none<U>>
Parameter(T &&x) : p{new data<U>{std::forward<T>(x)}} {}
/**
* @brief Overloads the assignment operator
* @param s The value to set the Parameter to
*/
Parameter &operator=(Parameter s) {
swap(*this, s);
return *this;
}
friend void swap(Parameter &s, Parameter &r) { std::swap(s.p, r.p); }
/**
* @brief Clears the Parameter
*/
void clear() {
delete p;
p = nullptr;
}
/**
* @brief Checks whether the Parameter is the given type
* @tparam T The type to check
* @return Whether the Parameter has the given type or not
*/
template <typename T> bool is() const {
return p ? p->is(type_id<T>()) : false;
}
/**
* @brief Returns the value of the Parameter
* @tparam T The type of the Parameter
* @return The value of the Parameter
* @warning If the type of the Parameter doesn't match the type of it's stored
* value, it will result in undefined behaviour.
*/
template <typename T> T &get() & { return stat<T>(); }
};
} // namespace RenderD7
+420
View File
@@ -0,0 +1,420 @@
#pragma once
/// c++ Includes
#include <algorithm>
#include <codecvt>
#include <cstring>
#include <filesystem>
#include <functional>
#include <iostream>
#include <locale>
#include <map>
#include <memory>
#include <random>
#include <stack>
#include <string>
#include <vector>
/// c includes
#include <dirent.h>
#include <stdio.h>
#include <sys/stat.h>
#include <time.h>
#include <unistd.h>
/// 3ds Includes
#include <3ds.h>
#include <citro2d.h>
#include <citro3d.h>
/// RenderD7 Includes
#include <renderd7/BitmapPrinter.hpp>
#include <renderd7/Color.hpp>
#include <renderd7/Draw.hpp>
#include <renderd7/FunctionTrace.hpp>
#include <renderd7/Hardware.hpp>
#include <renderd7/Image.hpp>
#include <renderd7/Memory.hpp>
#include <renderd7/Ovl.hpp>
#include <renderd7/ResultDecoder.hpp>
#include <renderd7/Screen.hpp>
#include <renderd7/Security.hpp>
#include <renderd7/Sheet.hpp>
#include <renderd7/Sprite.hpp>
#include <renderd7/SpriteAnimation.hpp>
#include <renderd7/Tasks.hpp>
#include <renderd7/Time.hpp>
#include <renderd7/Toast.hpp>
#include <renderd7/bmp.hpp>
#include <renderd7/bmpconverter.hpp>
#include <renderd7/external/lodepng.h>
#include <renderd7/ini.hpp>
#include <renderd7/lang.hpp>
#include <renderd7/parameter.hpp>
#include <renderd7/stringtool.hpp>
#include <renderd7/thread.hpp>
#define RENDERD7VSTRING "0.9.4"
#define CHANGELOG \
"0.9.4: Implement new Security System\n To prevent from crashes\nImplement " \
"Functiontrace for better\nTiming Tests\nImplement MemAlloc Tracker (only " \
"size)\nAdd some new Overlays (not functional yet)\nComplete Rewrite of " \
"Overlay System\nFixed the FrameEnd Crash\nNew System to get Hardware " \
"Info\nRemoved RD7SR\n0.9.3: Completly Documanted Everything\nFix typo " \
"in " \
"Sprite::getHeight()\nRemove Deprecated/Useless Stuff\n0.9.2: Add " \
"NpiSplashVideo\nNvid Support(v0.0.1)\nAdd " \
"Basic RenderD7 " \
"Splash\nFaster Graphics Init\nFade Effects\nFix Screen for this " \
"Changelog\n0.9.1: Fix Critical bug in\nSpritesheet animations\nFix " \
"Color " \
"Conver(Hex)\n0.9.0: Remove Stupid try of Console\nAdd Services list and " \
"Clean up " \
"Code.\nAlso added Minimal Init for hax2.x\n0.8.5: Fix Deltatime \n0.8.4: " \
"A lot of Fixes and new\nFeatures for BitmapPrinter! \n0.8.3: Addet " \
"Overlaycount to Info\nand Addet ResultDecoder for errors.\n0.8.2: Fix a " \
"lot of Stuff and\nadd c++17 based filesystem class.\n0.8.1: Add abillity " \
"to Get Stdout as string\nto render it to the screen.\n0.8.0: Implement " \
"BitmapPrinter\n0.7.3: Implement Over\nRender Overlay Framework\n0.7.2: " \
"Implement MT to csv file\nsaving.(removed) Add RGB2HEX.\n0.7.1: Add the " \
"New Overlay Handler. Its\nJust in code and does nothing yet.\n0.7.0: Made " \
"Big Progress In the MT\nOvl but it still crashes On\na Scnd " \
"C3D_FrameEnd()." \
"\nImplement 800px but\ndoesn't work that good. \n0.6.2: Fix Crash when " \
"exiting\ntrouth Home Menu.\n0.6.10: rewrite Threadsystem,\nImprove " \
"framerate\n0.6.02: Fix Code in lang.hpp\nadd Draw Text Left " \
"Function\n(Right since 0.7.0).\nadd changelog\n0.6.01: add Threading " \
"system.\n0.6.0: Better " \
"Scene Management\n0.5.0: Fixed some Bugs!\n0.4.0: Trying to fix " \
"Filesystem and Bugs!\n0.3.0: Recreate D7-Core into RenderD7!\n0.2.0: " \
"Trying to create Animations of\nImages instead of Sheets!\n0.1.0: Initial " \
"Release of\nD7-Core sprite animation plugin!"
#define DEFAULT_CENTER 0.5f
#define RD7_DEPRECATED // __attribute__ ((deprecated))
/// @param d7_hDown Current Key Down
extern u32 d7_hDown;
/// @param d7_hHeld Current Key Held
extern u32 d7_hHeld;
/// @param d7_hUp Current Key Up
extern u32 d7_hUp;
/// @param d7_touch Current Touch Position
extern touchPosition d7_touch;
/// @param dspststus Dsp Status String
extern std::string dspststus;
/// @param rd7_do_splash Config Value To Enable RenderD7 Splash
extern bool rd7_do_splash;
/// @param rd7_enable_memtrack Config Value to Track Mem Allocations
extern bool rd7_enable_memtrack;
/// RenderD7
namespace RenderD7 {
/// @brief Get Deltatime
/// @return Deltatime
float GetDeltaTime();
/// @brief Keyboard
enum kbd {
/// @brief libctru Keyboard
SWKBD,
/// @brief Unk (Not Usable)
BKBD
};
/// @brief Keyboar Type
enum kbd_type { NUMPAD, STANDARD };
/// @brief A Button
struct TObject {
int x; ///< Position X
int y; ///< Position Y
int w; ///< Button Width
int h; ///< Button Height
std::string text = ""; ///< Text
float txtsize = 0.7f; ///< Set Text Size
};
/// @brief Scene Class
class Scene {
public:
/// @brief Stack of the Scenes
static std::stack<std::unique_ptr<Scene>> scenes;
/// @brief Deconstructor
virtual ~Scene() {}
/// @brief Logic To Overide
/// @param hDown Key Down
/// @param hHeld Key Held
/// @param hUp Key Up
/// @param touch Touch Position
virtual void Logic(u32 hDown, u32 hHeld, u32 hUp, touchPosition touch) = 0;
/// @brief Draw Func to Override
virtual void Draw() const = 0;
/// @brief Push a Scene to Stack
/// @param scene Scene to Push
/// @param fade FadeEffect (Not Correctly Implementet yet)
static void Load(std::unique_ptr<Scene> scene, bool fade = false);
/// @brief Go Back a Scene
static void Back();
/// @brief do the Draw (Called in RenderD7::MainLoop())
static void doDraw();
/// @brief do the Logic (Called in RenderD7::MainLoop())
/// @param hDown Key Down
/// @param hHeld Key Held
/// @param hUp Key Up
/// @param touch Touch Positon
static void doLogic(u32 hDown, u32 hHeld, u32 hUp, touchPosition touch);
};
/// @brief Integrated Setting Menu of RenderD7
class RSettings : public RenderD7::Scene {
private:
/// @brief Calculate the Changelog Screen Stuff
/// @param lines vector of Lines
/// @param screen_index Current Screen
/// @param screens Count of Possible Screens
void calculate_screens(const std::vector<std::string> &lines,
int &screen_index, int &screens);
/// @brief State (Define for Menus)
enum RState {
RSETTINGS,
RINFO,
RSERVICES,
RCLOG,
RMCONFIG,
RFTRACE,
RSECM,
RCREDITS
};
/// @param m_state Current menu State (Default=MainMenu aka RSETTINGS)
RenderD7::RSettings::RState m_state = RenderD7::RSettings::RState::RSETTINGS;
/// @param screens Count of Changelog Screens
int screens = 0;
/// @param screen_index Current Changelog Screen
int screen_index = 0;
/// @param lines Vector of Changelog-Lines
std::vector<std::string> lines;
/// @brief Position in FTrace Menu
int ftrace_index = 0;
/// @param mtovlstate State of Metricks Overlay
std::string mtovlstate = "false";
/// @param mtscreenstate Screen the Overlay is Set to
std::string mtscreenstate = "Top";
/// @param buttons Vector of Buttons
std::vector<RenderD7::TObject> buttons = {
{20, 35, 120, 35, "NotYET"}, {20, 85, 120, 35, "Changelog"},
{20, 135, 120, 35, "Metrik-Ovl"}, {20, 185, 120, 35, "Tasks"},
{180, 35, 120, 35, "FTrace"}, {180, 85, 120, 35, "Credits"},
{180, 135, 120, 35, "Info"}, {180, 185, 120, 35, "Security"}};
public:
/// @brief Constructor
RSettings();
/// @brief Override for Draw
/// @param
void Draw(void) const override;
/// @brief Deconstructor
~RSettings();
/// @brief Override for Logic
/// @param hDown Key Down
/// @param hHeld Key Held
/// @param hUp Key Up
/// @param touch Touch Position
void Logic(u32 hDown, u32 hHeld, u32 hUp, touchPosition touch) override;
};
/// @brief Show Up the RenderD7-Settings Menu
void LoadSettings();
/// @brief DspNotFound Error Toast (Deprectated)
class DSP_NF : public RenderD7::Ovl {
public:
/// @brief Constructor
DSP_NF();
/// @brief Override for Draw
void Draw(void) const override;
/// @brief Override for Logic
void Logic() override;
private:
/// @param msgposy Y Position of Toast
int msgposy = 240;
/// @param delay Delay of Toast
int delay = 0;
};
/// @brief Get A Rendom Int
/// @param b From
/// @param e To
/// @return Random Int
int GetRandomInt(int b, int e);
/// @brief Short a String with (..,)
/// @param in Input string
/// @param size Size of Input Text
/// @param maxlen Max length of texr
/// @param font Custom Font for Correct Size Calculation
/// @return Shorted String
std::string ShortString(std::string in, float size, int maxlen,
C2D_Font font = nullptr);
/// @brief DrawMetrikOvl (YOUR OWN RISK)
void DrawMetrikOvl();
/// @brief Draw Image from RenderD7 Sheet
/// @param sheet Spritesheet
/// @param index Image index Value
/// @param x Pos X
/// @param y Pos Y
/// @param scaleX Scale on X-Axis
/// @param scaleY Scale on Y-Axis
/// @return success ?
bool DrawImageFromSheet(RenderD7::Sheet *sheet, size_t index, float x, float y,
float scaleX = 1.0, float scaleY = 1.0);
/// @brief Display the Npi-D7 Video Intro (NVID)
void DoNpiIntro();
/// @brief Fade In
/// @param duration Duration in Frames
void FadeIn();
/// @brief Fade Out
/// @param duration Duration in Frames
void FadeOut();
/// @brief Display Fade Effects
void FadeDisplay();
namespace Error {
/// @brief DEPRECATED Display Error for n Seconds
/// @param toptext Head Text
/// @param errortext Error Text
/// @param timesec Time n to Display in Seconds
void DisplayError(std::string toptext, std::string errortext, int timesec = 3);
/// @brief Display A Fatal Error
/// @param toptext Head Text
/// @param errortext Error Text
void DisplayFatalError(std::string toptext, std::string errortext);
} // namespace Error
namespace Init {
/// @brief Init Default RenderD7
/// @param app_name Name of Your App
/// @return ResCode
Result Main(std::string app_name = "RD7Game");
/// @brief Init Minimal RenderD7 (For better Hax2.x support)
/// @param app_name Name of Your App
/// @return ResCode
Result Minimal(std::string app_name = "RD7Game");
/// @brief Reload the Graphics Engine
/// @return ResCode
Result Reload();
/// @brief Init Graphics Only (NOT SUPPORTET use Reload)
void Graphics();
/// @brief Init Ndsp for Sounds
void NdspFirm();
} // namespace Init
namespace Msg {
/// @brief Display A Message
/// @param titletxt Header Text
/// @param subtext Message Text
/// @param target Screen
void Display(std::string titletxt, std::string subtext,
C3D_RenderTarget *target);
/// @brief Display A Message Wit Progress
/// @param titletext Header Text
/// @param subtext Message Text
/// @param current Current Progress
/// @param total Total Progress
/// @param prgbarcolor Color of Progressbar
void DisplayWithProgress(std::string titletext, std::string subtext,
float current, float total, u32 prgbarcolor);
} // namespace Msg
namespace Convert {
/// @brief Convert a String to Flaot
/// @param inp Input String
/// @return Float
inline float StringtoFloat(std::string inp) { return std::atof(inp.c_str()); }
/// @brief Convert String to Int
/// @param inp Input String
/// @return Int
inline int StringtoInt(std::string inp) { return std::atoi(inp.c_str()); }
/// @brief Convert a Float to Bool
/// @param inp Input Float
/// @return Bool
inline bool FloatToBool(float inp) { return (inp == 1 ? true : false); }
} // namespace Convert
namespace FS {
/// @brief Check if File exists
/// @param path Path to the File
/// @return exists or not
bool FileExist(const std::string &path);
} // namespace FS
/// @brief Check if Ndsp is Init
/// @return is or not
bool IsNdspInit();
/// @brief Get Current Framerate as String
/// @return Framerate String
std::string GetFramerate();
/// @brief MainLoop of RenderD7s
/// @return Is Still Running or not
bool MainLoop();
/// @brief Exit App (brak the MainLoop)
void ExitApp();
/// @brief Clear the Citro2D TextBuffers
/// @param
void ClearTextBufs(void);
/// @brief Open A Keyboard (SWKBD)
/// @param lenght Length of the string
/// @param tp Type of The Keyboard
/// @return the string if pressed Ok
std::string Kbd(int lenght, SwkbdType tp);
/// @brief Draw Overlays And end the Frame. DO NEVER USE C3D_FRAMEEND cause it
/// breaks Overlay crash Security
void FrameEnd();
/// @brief Textless Button
struct TLBtn {
int x; ///< Position X
int y; ///< Position Y
int w; ///< Button Width
int h; ///< Button Height
};
/// @brief Draw Buttons
/// @param tobjects Vector of Buttons
/// @param color Color of the Buttons
/// @param txtcolor Color of The Text
/// @param selection Positon of Selection
/// @param selbgcolor Selection BackgroundColor
/// @param selcolor Selection Color
void DrawTObjects(std::vector<RenderD7::TObject> tobjects, u32 color,
u32 txtcolor, int selection = -1,
u32 selbgcolor = RenderD7::Color::Hex("#2D98AF"),
u32 selcolor = RenderD7::Color::Hex("#000000"));
/// @brief Draw A Single Button
/// @param tobject Button
/// @param tobjectindex Button Index
/// @param color Color of the Button
/// @param txtcolor Color of The Text
void DrawSTObject(std::vector<RenderD7::TObject> tobject, int tobjectindex,
u32 color, u32 txtcolor);
/// @brief Touched A Button
/// @param touch Touch Position
/// @param button Button
/// @return is touched or not
bool touchTObj(touchPosition touch, RenderD7::TObject button);
/// @brief Touched A Textless Button
/// @param touch Touch Position
/// @param button Button
/// @return is touched or not
bool touchTLBtn(touchPosition touch, RenderD7::TLBtn button);
/// @brief Draw Textless Buttons
/// @param tobjects Vector of Buttons
/// @param color Color of the Buttons
/// @param selection Positon of Selection
/// @param selbgcolor Selection BackgroundColor
/// @param selcolor Selection Color
void DrawTLBtns(std::vector<RenderD7::TLBtn> btns, u32 color,
int selection = -1,
u32 selbgcolor = RenderD7::Color::Hex("#2D98AF"),
u32 selcolor = RenderD7::Color::Hex("#000000"));
} // namespace RenderD7
@@ -0,0 +1,5 @@
#pragma once
#include <cstddef>
extern unsigned char renderd7_logo[];
extern size_t renderd7_logo_size;
+30
View File
@@ -0,0 +1,30 @@
#pragma once
#include <3ds.h>
#include <string>
/** Sound Class */
class sound {
public:
/// \brief Construct new Soundeffect
/// \param path Path to the .wav file
/// \param channel the channel 1-23
/// \param toloop true:loop the sound, false: don't loop
sound(const std::string &path, int channel = 1, bool toloop = false);
/// @brief Deconstructor
~sound();
/// @brief Play the sound
void play();
/// @brief Stop the sound
void stop();
private:
/// \param dataSize Size of the filedata
u32 dataSize;
/// \param waveBuf For ndsp
ndspWaveBuf waveBuf;
/// \param data Memmory data of the sound
uint8_t *data = NULL;
/// \param chnl Channel of the sound
int chnl;
};
@@ -0,0 +1,81 @@
#pragma once
#include <iomanip>
#include <iostream>
#include <sstream>
#include <string>
namespace RenderD7 {
/// @brief Check if A String ends with
/// @param name Input String
/// @param extensions Extensions to Check for
/// @return Ends with or not
inline bool NameIsEndingWith(const std::string &name,
const std::vector<std::string> &extensions) {
if (name.substr(0, 2) == "._")
return false;
if (name.size() == 0)
return false;
if (extensions.size() == 0)
return true;
for (int i = 0; i < (int)extensions.size(); i++) {
const std::string ext = extensions.at(i);
if (strcasecmp(name.c_str() + name.size() - ext.size(), ext.c_str()) == 0)
return true;
}
return false;
}
/// @brief Format Milliseconds to clean string (Stolen from one of my Mc
/// Plugins)
/// @param t_time Time in ms
/// @return String
inline std::string MsTimeFmt(float t_time) {
std::ostringstream oss;
if (t_time < 0.001f) {
oss << std::fixed << std::setprecision(2) << t_time * 1000.0f << "ns";
} else if (t_time < 1.0f) {
oss << std::fixed << std::setprecision(2) << t_time << "ms";
} else if (t_time < 60000.0f) {
int seconds = static_cast<int>(t_time / 1000.0f);
float milliseconds = t_time - (seconds * 1000.0f);
if (seconds > 0) {
oss << seconds << "s ";
}
oss << std::fixed << std::setprecision(2) << milliseconds << "ms";
} else {
int minutes = static_cast<int>(t_time / 60000.0f);
int seconds = static_cast<int>((t_time - (minutes * 60000.0f)) / 1000.0f);
float milliseconds = t_time - (minutes * 60000.0f) - (seconds * 1000.0f);
oss << minutes << "m ";
if (seconds > 0 || milliseconds > 0.0f) {
oss << seconds << "s ";
}
if (milliseconds > 0.0f) {
oss << std::fixed << std::setprecision(2) << milliseconds << "ms";
}
}
return oss.str();
}
} // namespace RenderD7
template <class T> T GetFileName(T const &path, T const &delims = "/\\") {
return path.substr(path.find_last_of(delims) + 1);
}
template <class T> T remove_ext(T const &filename) {
typename T::size_type const p(filename.find_last_of('.'));
return p > 0 && p != T::npos ? filename.substr(0, p) : filename;
}
template <typename T> std::string Int_To_Hex(T i) {
std::stringstream stream;
stream << "0x" << std::setfill('0') << std::setw(sizeof(T) * 2) << std::hex
<< i;
return stream.str();
}
+122
View File
@@ -0,0 +1,122 @@
#pragma once
#include <3ds.h>
#include <atomic>
#include <functional>
#include <renderd7/parameter.hpp>
#include <string>
using CTRU_Thread = Thread;
#define THREAD_STACK_SIZE 0x1000
namespace RenderD7 {
class Thread {
public:
/**
* @brief Default constructor
* @note This should only be called when calling m3d::Thread::initialize()
* before calling m3d::Thread::start()
*/
Thread();
/**
* @brief Constructs the thread
* @param t_function The thread function
* @param t_parameter The parameter to pass to the function
* @param t_autostart Whether the thread should start instantly
* @param t_detached Whether the thread starts detached or not
* @param t_stackSize The stacksize allocated for the thread in bytes (rounded
* to multiples of 8 bytes)
* @note t_function needs to be of type `void` and take one (and only one)
* parameter of type m3d::Parameter
* @warning If the thread priority is lower than the priority of the calling
* thread, the thread will never get executed. Use
* m3d::Thread::getCurrentPriority() to get the priority of the current thread
*/
Thread(std::function<void(RenderD7::Parameter)> t_function,
RenderD7::Parameter t_parameter = nullptr, bool t_autostart = false,
bool t_detached = false,
unsigned long long int t_stackSize = 4 * 1024);
/**
* @brief Destructs the thread
*/
virtual ~Thread();
/**
* @brief Initializes the thread
* @param t_function The thread function
* @param t_parameter The parameter to pass to the function
* @param t_autostart Whether the thread should start instantly
* @param t_detached Whether the thread starts detached or not
* @param t_stackSize The stacksize allocated for the thread in bytes (rounded
* to multiples of 8 bytes)
* @note t_function needs to be of type `void` and take one (and only one)
* parameter of type m3d::Parameter
* @warning If the thread priority is lower than the priority of the calling
* thread, the thread will never get executed. Use
* m3d::Thread::getCurrentPriority() to get the priority of the current thread
*/
void initialize(std::function<void(RenderD7::Parameter)> t_function,
RenderD7::Parameter t_parameter = nullptr,
bool t_autostart = false, bool t_detached = false,
unsigned long long int t_stackSize = 4 * 1024);
/**
* @brief Sets the size of the stack that gets allocated for the next thread
* that get's started
* @param t_stackSize The allocated space in bytes (rounded to multiples of 8
* bytes)
*/
void setStackSize(unsigned long long int t_stackSize);
/**
* @brief Starts the thread. To restart it, call Thread::join() before
* @param t_detached Whether the thread should start detached or not
*/
void start(bool t_detached = false);
/**
* @brief Detaches the thread
*/
void kill();
/**
* @brief Waits for the thread to finish
* @param t_timeout The timeout in nanoseconds. Leave it for no timeout
*/
void join(long long unsigned int t_timeout = U64_MAX);
bool isRunning();
/**
* @brief Puts the thread to sleep
*
* This is needed if you have multiple threads running at the same time. It
* doesn't affect the execution-time of the thread, it just makes it possible
* for the other threads to get their chance to shine.
*/
static void sleep();
/**
* @brief Sleeps for the given time
* @param t_milliseconds The time to sleep in milliseconds
*/
static void sleep(int t_milliseconds);
private:
struct ThreadData {
RenderD7::Parameter m_parameter;
std::function<void(RenderD7::Parameter)> m_function;
std::atomic<bool> *m_running;
};
static void threadFunction(void *t_arg);
/* data */
int m_priority, m_stackSize;
bool m_started;
std::atomic<bool> m_running;
RenderD7::Thread::ThreadData m_data;
CTRU_Thread m_thread;
};
} // namespace RenderD7
@@ -0,0 +1,5 @@
#pragma once
#include <cstddef>
extern unsigned char ui_elements[];
extern size_t ui_elements_size;