mirror of
https://github.com/dborth/vbagx.git
synced 2024-12-25 18:21:51 +01:00
new font, rewritten PNGU, menu tweaks, optimized text code
This commit is contained in:
parent
5166ca2b61
commit
c926152762
Binary file not shown.
@ -109,7 +109,7 @@ GuiFileBrowser::GuiFileBrowser(int w, int h)
|
||||
fileListText[i] = new GuiText(NULL, 20, (GXColor){0, 0, 0, 0xff});
|
||||
fileListText[i]->SetAlignment(ALIGN_LEFT, ALIGN_MIDDLE);
|
||||
fileListText[i]->SetPosition(5,0);
|
||||
fileListText[i]->SetMaxWidth(380);
|
||||
fileListText[i]->SetMaxWidth(450);
|
||||
|
||||
fileListBg[i] = new GuiImage(bgFileSelectionEntry);
|
||||
fileListIcon[i] = NULL;
|
||||
|
@ -20,40 +20,7 @@ GuiImageData::GuiImageData(const u8 * i)
|
||||
height = 0;
|
||||
|
||||
if(i)
|
||||
{
|
||||
PNGUPROP imgProp;
|
||||
IMGCTX ctx = PNGU_SelectImageFromBuffer(i);
|
||||
|
||||
if(!ctx)
|
||||
return;
|
||||
|
||||
int res = PNGU_GetImageProperties(ctx, &imgProp);
|
||||
|
||||
if(res == PNGU_OK)
|
||||
{
|
||||
int len = (imgProp.imgWidth * imgProp.imgHeight) <<2;
|
||||
if(len%32) len += (32-len%32);
|
||||
data = (u8 *)memalign (32, len);
|
||||
|
||||
if(data)
|
||||
{
|
||||
res = PNGU_DecodeTo4x4RGBA8 (ctx, imgProp.imgWidth, imgProp.imgHeight, data, 255);
|
||||
|
||||
if(res == PNGU_OK)
|
||||
{
|
||||
width = imgProp.imgWidth;
|
||||
height = imgProp.imgHeight;
|
||||
DCFlushRange(data, len);
|
||||
}
|
||||
else
|
||||
{
|
||||
free(data);
|
||||
data = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
PNGU_ReleaseImageContext (ctx);
|
||||
}
|
||||
data = DecodePNG(i, &width, &height);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -237,126 +237,130 @@ void GuiText::Draw()
|
||||
fontSystem[newSize] = new FreeTypeGX(newSize);
|
||||
currentSize = newSize;
|
||||
}
|
||||
|
||||
u8 maxChar;
|
||||
|
||||
if(maxWidth > 0)
|
||||
{
|
||||
char * tmpText = strdup(origText);
|
||||
u8 maxChar = int((float((maxWidth<<1))) / (float(newSize)));
|
||||
|
||||
if(!textDyn)
|
||||
{
|
||||
if(strlen(tmpText) > maxChar)
|
||||
tmpText[maxChar] = 0;
|
||||
textDyn = charToWideChar(tmpText);
|
||||
}
|
||||
|
||||
if(textScroll == SCROLL_HORIZONTAL)
|
||||
{
|
||||
int textlen = strlen(origText);
|
||||
|
||||
if(textlen > maxChar && (FrameTimer % textScrollDelay == 0))
|
||||
{
|
||||
if(textScrollInitialDelay)
|
||||
{
|
||||
--textScrollInitialDelay;
|
||||
}
|
||||
else
|
||||
{
|
||||
++textScrollPos;
|
||||
if(textScrollPos > textlen-1)
|
||||
{
|
||||
textScrollPos = 0;
|
||||
textScrollInitialDelay = TEXT_SCROLL_INITIAL_DELAY;
|
||||
}
|
||||
|
||||
strncpy(tmpText, &origText[textScrollPos], maxChar-1);
|
||||
tmpText[maxChar-1] = 0;
|
||||
|
||||
int dynlen = strlen(tmpText);
|
||||
|
||||
if(dynlen+2 < maxChar)
|
||||
{
|
||||
tmpText[dynlen] = ' ';
|
||||
tmpText[dynlen+1] = ' ';
|
||||
strncat(&tmpText[dynlen+2], origText, maxChar - dynlen - 2);
|
||||
}
|
||||
if(textDyn) delete[] textDyn;
|
||||
textDyn = charToWideChar(tmpText);
|
||||
}
|
||||
}
|
||||
if(textDyn)
|
||||
fontSystem[currentSize]->drawText(this->GetLeft(), this->GetTop(), textDyn, c, style);
|
||||
}
|
||||
else if(wrap)
|
||||
{
|
||||
int lineheight = newSize + 6;
|
||||
int txtlen = wcslen(text);
|
||||
int i = 0;
|
||||
int ch = 0;
|
||||
int linenum = 0;
|
||||
int lastSpace = -1;
|
||||
int lastSpaceIndex = -1;
|
||||
wchar_t * textrow[20];
|
||||
|
||||
while(ch < txtlen)
|
||||
{
|
||||
if(i == 0)
|
||||
textrow[linenum] = new wchar_t[txtlen + 1];
|
||||
|
||||
textrow[linenum][i] = text[ch];
|
||||
textrow[linenum][i+1] = 0;
|
||||
|
||||
if(text[ch] == ' ' || ch == txtlen-1)
|
||||
{
|
||||
if(wcslen(textrow[linenum]) >= maxChar)
|
||||
{
|
||||
if(lastSpace >= 0)
|
||||
{
|
||||
textrow[linenum][lastSpaceIndex] = 0; // discard space, and everything after
|
||||
ch = lastSpace; // go backwards to the last space
|
||||
lastSpace = -1; // we have used this space
|
||||
lastSpaceIndex = -1;
|
||||
}
|
||||
++linenum;
|
||||
i = -1;
|
||||
}
|
||||
else if(ch == txtlen-1)
|
||||
{
|
||||
++linenum;
|
||||
}
|
||||
}
|
||||
if(text[ch] == ' ' && i >= 0)
|
||||
{
|
||||
lastSpace = ch;
|
||||
lastSpaceIndex = i;
|
||||
}
|
||||
++ch;
|
||||
++i;
|
||||
}
|
||||
|
||||
int voffset = 0;
|
||||
|
||||
if(alignmentVert == ALIGN_MIDDLE)
|
||||
voffset = (lineheight >> 1) * (1-linenum);
|
||||
|
||||
int left = this->GetLeft();
|
||||
int top = this->GetTop() + voffset;
|
||||
|
||||
for(i=0; i < linenum; ++i)
|
||||
{
|
||||
fontSystem[currentSize]->drawText(left, top+i*lineheight, textrow[i], c, style);
|
||||
delete[] textrow[i];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
fontSystem[currentSize]->drawText(this->GetLeft(), this->GetTop(), textDyn, c, style);
|
||||
}
|
||||
free(tmpText);
|
||||
}
|
||||
else
|
||||
if(maxWidth == 0)
|
||||
{
|
||||
fontSystem[currentSize]->drawText(this->GetLeft(), this->GetTop(), text, c, style);
|
||||
goto done;
|
||||
}
|
||||
|
||||
maxChar = int((float((maxWidth<<1))) / (float(newSize))); // approximate
|
||||
|
||||
if(wrap)
|
||||
{
|
||||
int lineheight = newSize + 6;
|
||||
int txtlen = wcslen(text);
|
||||
int i = 0;
|
||||
int ch = 0;
|
||||
int linenum = 0;
|
||||
int lastSpace = -1;
|
||||
int lastSpaceIndex = -1;
|
||||
wchar_t * textrow[20];
|
||||
|
||||
while(ch < txtlen)
|
||||
{
|
||||
if(i == 0)
|
||||
textrow[linenum] = new wchar_t[txtlen + 1];
|
||||
|
||||
textrow[linenum][i] = text[ch];
|
||||
textrow[linenum][i+1] = 0;
|
||||
|
||||
if(text[ch] == ' ' || ch == txtlen-1)
|
||||
{
|
||||
if(wcslen(textrow[linenum]) >= maxChar)
|
||||
{
|
||||
if(lastSpace >= 0)
|
||||
{
|
||||
textrow[linenum][lastSpaceIndex] = 0; // discard space, and everything after
|
||||
ch = lastSpace; // go backwards to the last space
|
||||
lastSpace = -1; // we have used this space
|
||||
lastSpaceIndex = -1;
|
||||
}
|
||||
++linenum;
|
||||
i = -1;
|
||||
}
|
||||
else if(ch == txtlen-1)
|
||||
{
|
||||
++linenum;
|
||||
}
|
||||
}
|
||||
if(text[ch] == ' ' && i >= 0)
|
||||
{
|
||||
lastSpace = ch;
|
||||
lastSpaceIndex = i;
|
||||
}
|
||||
++ch;
|
||||
++i;
|
||||
}
|
||||
|
||||
int voffset = 0;
|
||||
|
||||
if(alignmentVert == ALIGN_MIDDLE)
|
||||
voffset = (lineheight >> 1) * (1-linenum);
|
||||
|
||||
int left = this->GetLeft();
|
||||
int top = this->GetTop() + voffset;
|
||||
|
||||
for(i=0; i < linenum; ++i)
|
||||
{
|
||||
fontSystem[currentSize]->drawText(left, top+i*lineheight, textrow[i], c, style);
|
||||
delete[] textrow[i];
|
||||
}
|
||||
goto done;
|
||||
}
|
||||
|
||||
if(textScroll == SCROLL_HORIZONTAL)
|
||||
{
|
||||
char *tmpText = strdup(gettext(origText));
|
||||
char *tmpText2 = strdup(tmpText);
|
||||
int textlen = strlen(tmpText);
|
||||
|
||||
if(textlen > maxChar && (FrameTimer % textScrollDelay == 0))
|
||||
{
|
||||
if(textScrollInitialDelay)
|
||||
{
|
||||
--textScrollInitialDelay;
|
||||
}
|
||||
else
|
||||
{
|
||||
++textScrollPos;
|
||||
if(textScrollPos > textlen-1)
|
||||
{
|
||||
textScrollPos = 0;
|
||||
textScrollInitialDelay = TEXT_SCROLL_INITIAL_DELAY;
|
||||
}
|
||||
|
||||
strncpy(tmpText, &tmpText2[textScrollPos], maxChar-1);
|
||||
tmpText[maxChar-1] = 0;
|
||||
|
||||
int dynlen = strlen(tmpText);
|
||||
|
||||
if(dynlen+2 < maxChar)
|
||||
{
|
||||
tmpText[dynlen] = ' ';
|
||||
tmpText[dynlen+1] = ' ';
|
||||
strncat(&tmpText[dynlen+2], tmpText2, maxChar - dynlen - 2);
|
||||
}
|
||||
if(textDyn) delete[] textDyn;
|
||||
textDyn = charToWideChar(tmpText);
|
||||
}
|
||||
}
|
||||
free(tmpText);
|
||||
free(tmpText2);
|
||||
}
|
||||
|
||||
if(!textDyn)
|
||||
{
|
||||
char *tmpText = strdup(gettext(origText));
|
||||
if(strlen(tmpText) > maxChar)
|
||||
tmpText[maxChar] = 0;
|
||||
textDyn = charToWideChar(tmpText);
|
||||
free(tmpText);
|
||||
}
|
||||
|
||||
fontSystem[currentSize]->drawText(this->GetLeft(), this->GetTop(), textDyn, c, style);
|
||||
done:
|
||||
this->UpdateEffects();
|
||||
}
|
||||
|
@ -3472,7 +3472,7 @@ static int MenuSettingsNetwork()
|
||||
GuiOptionBrowser optionBrowser(552, 248, &options);
|
||||
optionBrowser.SetPosition(0, 108);
|
||||
optionBrowser.SetAlignment(ALIGN_CENTRE, ALIGN_TOP);
|
||||
optionBrowser.SetCol2Position(275);
|
||||
optionBrowser.SetCol2Position(290);
|
||||
|
||||
HaltGui();
|
||||
GuiWindow w(screenwidth, screenheight);
|
||||
|
@ -1,31 +1,41 @@
|
||||
/********************************************************************************************
|
||||
|
||||
PNGU Version : 0.2a
|
||||
|
||||
Coder : frontier
|
||||
|
||||
More info : http://frontier-dev.net
|
||||
|
||||
Modified by Tantric, 2009
|
||||
|
||||
*
|
||||
* PNGU
|
||||
*
|
||||
* Original author: frontier (http://frontier-dev.net)
|
||||
* Modified by Tantric, 2009-2010
|
||||
*
|
||||
********************************************************************************************/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <malloc.h>
|
||||
#include <gccore.h>
|
||||
#include "pngu.h"
|
||||
#include "png.h"
|
||||
#include <png.h>
|
||||
|
||||
// Constants
|
||||
#define PNGU_SOURCE_BUFFER 1
|
||||
#define PNGU_SOURCE_DEVICE 2
|
||||
#define PNGU_SOURCE_BUFFER 1
|
||||
#define PNGU_SOURCE_DEVICE 2
|
||||
|
||||
// Prototypes of helper functions
|
||||
int pngu_info (IMGCTX ctx);
|
||||
int pngu_decode (IMGCTX ctx, PNGU_u32 width, PNGU_u32 height, PNGU_u32 stripAlpha);
|
||||
void pngu_free_info (IMGCTX ctx);
|
||||
void pngu_read_data_from_buffer (png_structp png_ptr, png_bytep data, png_size_t length);
|
||||
void pngu_write_data_to_buffer (png_structp png_ptr, png_bytep data, png_size_t length);
|
||||
void pngu_flush_data_to_buffer (png_structp png_ptr);
|
||||
int pngu_clamp (int value, int min, int max);
|
||||
// Return codes
|
||||
#define PNGU_OK 0
|
||||
#define PNGU_ODD_WIDTH 1
|
||||
#define PNGU_ODD_STRIDE 2
|
||||
#define PNGU_INVALID_WIDTH_OR_HEIGHT 3
|
||||
#define PNGU_FILE_IS_NOT_PNG 4
|
||||
#define PNGU_UNSUPPORTED_COLOR_TYPE 5
|
||||
#define PNGU_NO_FILE_SELECTED 6
|
||||
#define PNGU_CANT_OPEN_FILE 7
|
||||
#define PNGU_CANT_READ_FILE 8
|
||||
#define PNGU_LIB_ERROR 9
|
||||
|
||||
// Color types
|
||||
#define PNGU_COLOR_TYPE_GRAY 1
|
||||
#define PNGU_COLOR_TYPE_GRAY_ALPHA 2
|
||||
#define PNGU_COLOR_TYPE_PALETTE 3
|
||||
#define PNGU_COLOR_TYPE_RGB 4
|
||||
#define PNGU_COLOR_TYPE_RGB_ALPHA 5
|
||||
#define PNGU_COLOR_TYPE_UNKNOWN 6
|
||||
|
||||
// PNGU Image context struct
|
||||
struct _IMGCTX
|
||||
@ -49,362 +59,42 @@ struct _IMGCTX
|
||||
|
||||
// PNGU Implementation
|
||||
|
||||
IMGCTX PNGU_SelectImageFromBuffer (const void *buffer)
|
||||
static void pngu_free_info (IMGCTX ctx)
|
||||
{
|
||||
IMGCTX ctx = NULL;
|
||||
|
||||
if (!buffer)
|
||||
return NULL;
|
||||
|
||||
ctx = malloc (sizeof (struct _IMGCTX));
|
||||
if (!ctx)
|
||||
return NULL;
|
||||
|
||||
ctx->buffer = (void *) buffer;
|
||||
ctx->source = PNGU_SOURCE_BUFFER;
|
||||
ctx->cursor = 0;
|
||||
ctx->filename = NULL;
|
||||
ctx->propRead = 0;
|
||||
ctx->infoRead = 0;
|
||||
|
||||
return ctx;
|
||||
}
|
||||
|
||||
IMGCTX PNGU_SelectImageFromDevice (const char *filename)
|
||||
{
|
||||
IMGCTX ctx = NULL;
|
||||
|
||||
if (!filename)
|
||||
return NULL;
|
||||
|
||||
ctx = malloc (sizeof (struct _IMGCTX));
|
||||
if (!ctx)
|
||||
return NULL;
|
||||
|
||||
ctx->buffer = NULL;
|
||||
ctx->source = PNGU_SOURCE_DEVICE;
|
||||
ctx->cursor = 0;
|
||||
|
||||
ctx->filename = malloc (strlen (filename) + 1);
|
||||
if (!ctx->filename)
|
||||
{
|
||||
free (ctx);
|
||||
return NULL;
|
||||
}
|
||||
strcpy(ctx->filename, filename);
|
||||
|
||||
ctx->propRead = 0;
|
||||
ctx->infoRead = 0;
|
||||
|
||||
return ctx;
|
||||
}
|
||||
|
||||
void PNGU_ReleaseImageContext (IMGCTX ctx)
|
||||
{
|
||||
if (!ctx)
|
||||
return;
|
||||
|
||||
if (ctx->filename)
|
||||
free (ctx->filename);
|
||||
|
||||
if ((ctx->propRead) && (ctx->prop.trans))
|
||||
free (ctx->prop.trans);
|
||||
|
||||
pngu_free_info (ctx);
|
||||
free (ctx);
|
||||
}
|
||||
|
||||
int PNGU_GetImageProperties (IMGCTX ctx, PNGUPROP *imgprop)
|
||||
{
|
||||
int res;
|
||||
|
||||
if (!ctx->propRead)
|
||||
{
|
||||
res = pngu_info (ctx);
|
||||
if (res != PNGU_OK)
|
||||
return res;
|
||||
}
|
||||
|
||||
*imgprop = ctx->prop;
|
||||
return PNGU_OK;
|
||||
}
|
||||
|
||||
int PNGU_DecodeTo4x4RGBA8 (IMGCTX ctx, PNGU_u32 width, PNGU_u32 height, void *buffer, PNGU_u8 default_alpha)
|
||||
{
|
||||
int result;
|
||||
PNGU_u32 x, y, qwidth, qheight;
|
||||
PNGU_u64 alphaMask;
|
||||
|
||||
// width and height need to be divisible by four
|
||||
if ((width % 4) || (height % 4))
|
||||
return PNGU_INVALID_WIDTH_OR_HEIGHT;
|
||||
|
||||
result = pngu_decode (ctx, width, height, 0);
|
||||
if (result != PNGU_OK)
|
||||
return result;
|
||||
|
||||
// Init some variables
|
||||
qwidth = width >> 2;
|
||||
qheight = height >> 2;
|
||||
|
||||
// Check is source image has an alpha channel
|
||||
if ( (ctx->prop.imgColorType == PNGU_COLOR_TYPE_GRAY_ALPHA) || (ctx->prop.imgColorType == PNGU_COLOR_TYPE_RGB_ALPHA) )
|
||||
{
|
||||
// Alpha channel present, copy image to the output buffer
|
||||
for (y = 0; y < qheight; y++)
|
||||
for (x = 0; x < qwidth; x++)
|
||||
{
|
||||
int blockbase = (y * qwidth + x) << 3;
|
||||
|
||||
PNGU_u32 y4 = y << 2;
|
||||
PNGU_u32 x16 = x << 4;
|
||||
|
||||
PNGU_u64 fieldA = *((PNGU_u64 *)(ctx->row_pointers[y4]+x16));
|
||||
PNGU_u64 fieldB = *((PNGU_u64 *)(ctx->row_pointers[y4]+x16+8));
|
||||
((PNGU_u64 *) buffer)[blockbase] =
|
||||
((fieldA & 0xFF00000000ULL) << 24) | ((fieldA & 0xFF00000000000000ULL) >> 8) |
|
||||
((fieldA & 0xFFULL) << 40) | ((fieldA & 0xFF000000ULL) << 8) |
|
||||
((fieldB & 0xFF00000000ULL) >> 8) | ((fieldB & 0xFF00000000000000ULL) >> 40) |
|
||||
((fieldB & 0xFFULL) << 8) | ((fieldB & 0xFF000000ULL) >> 24);
|
||||
((PNGU_u64 *) buffer)[blockbase+4] =
|
||||
((fieldA & 0xFFFF0000000000ULL) << 8) | ((fieldA & 0xFFFF00ULL) << 24) |
|
||||
((fieldB & 0xFFFF0000000000ULL) >> 24) | ((fieldB & 0xFFFF00ULL) >> 8);
|
||||
|
||||
fieldA = *((PNGU_u64 *)(ctx->row_pointers[y4+1]+x16));
|
||||
fieldB = *((PNGU_u64 *)(ctx->row_pointers[y4+1]+x16+8));
|
||||
((PNGU_u64 *) buffer)[blockbase+1] =
|
||||
((fieldA & 0xFF00000000ULL) << 24) | ((fieldA & 0xFF00000000000000ULL) >> 8) |
|
||||
((fieldA & 0xFFULL) << 40) | ((fieldA & 0xFF000000ULL) << 8) |
|
||||
((fieldB & 0xFF00000000ULL) >> 8) | ((fieldB & 0xFF00000000000000ULL) >> 40) |
|
||||
((fieldB & 0xFFULL) << 8) | ((fieldB & 0xFF000000ULL) >> 24);
|
||||
((PNGU_u64 *) buffer)[blockbase+5] =
|
||||
((fieldA & 0xFFFF0000000000ULL) << 8) | ((fieldA & 0xFFFF00ULL) << 24) |
|
||||
((fieldB & 0xFFFF0000000000ULL) >> 24) | ((fieldB & 0xFFFF00ULL) >> 8);
|
||||
|
||||
fieldA = *((PNGU_u64 *)(ctx->row_pointers[y4+2]+x16));
|
||||
fieldB = *((PNGU_u64 *)(ctx->row_pointers[y4+2]+x16+8));
|
||||
((PNGU_u64 *) buffer)[blockbase+2] =
|
||||
((fieldA & 0xFF00000000ULL) << 24) | ((fieldA & 0xFF00000000000000ULL) >> 8) |
|
||||
((fieldA & 0xFFULL) << 40) | ((fieldA & 0xFF000000ULL) << 8) |
|
||||
((fieldB & 0xFF00000000ULL) >> 8) | ((fieldB & 0xFF00000000000000ULL) >> 40) |
|
||||
((fieldB & 0xFFULL) << 8) | ((fieldB & 0xFF000000ULL) >> 24);
|
||||
((PNGU_u64 *) buffer)[blockbase+6] =
|
||||
((fieldA & 0xFFFF0000000000ULL) << 8) | ((fieldA & 0xFFFF00ULL) << 24) |
|
||||
((fieldB & 0xFFFF0000000000ULL) >> 24) | ((fieldB & 0xFFFF00ULL) >> 8);
|
||||
|
||||
fieldA = *((PNGU_u64 *)(ctx->row_pointers[y4+3]+x16));
|
||||
fieldB = *((PNGU_u64 *)(ctx->row_pointers[y4+3]+x16+8));
|
||||
((PNGU_u64 *) buffer)[blockbase+3] =
|
||||
((fieldA & 0xFF00000000ULL) << 24) | ((fieldA & 0xFF00000000000000ULL) >> 8) |
|
||||
((fieldA & 0xFFULL) << 40) | ((fieldA & 0xFF000000ULL) << 8) |
|
||||
((fieldB & 0xFF00000000ULL) >> 8) | ((fieldB & 0xFF00000000000000ULL) >> 40) |
|
||||
((fieldB & 0xFFULL) << 8) | ((fieldB & 0xFF000000ULL) >> 24);
|
||||
((PNGU_u64 *) buffer)[blockbase+7] =
|
||||
((fieldA & 0xFFFF0000000000ULL) << 8) | ((fieldA & 0xFFFF00ULL) << 24) |
|
||||
((fieldB & 0xFFFF0000000000ULL) >> 24) | ((fieldB & 0xFFFF00ULL) >> 8);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// No alpha channel present, copy image to the output buffer
|
||||
alphaMask = (((PNGU_u64)default_alpha) << 56) | (((PNGU_u64)default_alpha) << 40) |
|
||||
(((PNGU_u64)default_alpha) << 24) | (((PNGU_u64)default_alpha) << 8);
|
||||
|
||||
for (y = 0; y < qheight; y++)
|
||||
for (x = 0; x < qwidth; x++)
|
||||
{
|
||||
int blockbase = (y * qwidth + x) << 3;
|
||||
|
||||
PNGU_u32 y4 = y << 2;
|
||||
PNGU_u32 x12 = x * 12;
|
||||
|
||||
PNGU_u64 field64 = *((PNGU_u64 *)(ctx->row_pointers[y4]+x12));
|
||||
PNGU_u64 field32 = (PNGU_u64) *((PNGU_u32 *)(ctx->row_pointers[y4]+x12+8));
|
||||
((PNGU_u64 *) buffer)[blockbase] =
|
||||
(((field64 & 0xFF00000000000000ULL) >> 8) | (field64 & 0xFF00000000ULL) |
|
||||
((field64 & 0xFF00ULL) << 8) | ((field32 & 0xFF0000ULL) >> 16) | alphaMask);
|
||||
((PNGU_u64 *) buffer)[blockbase+4] =
|
||||
(((field64 & 0xFFFF0000000000ULL) << 8) | ((field64 & 0xFFFF0000ULL) << 16) |
|
||||
((field64 & 0xFFULL) << 24) | ((field32 & 0xFF000000ULL) >> 8) | (field32 & 0xFFFFULL));
|
||||
|
||||
field64 = *((PNGU_u64 *)(ctx->row_pointers[y4+1]+x12));
|
||||
field32 = (PNGU_u64) *((PNGU_u32 *)(ctx->row_pointers[y4+1]+x12+8));
|
||||
((PNGU_u64 *) buffer)[blockbase+1] =
|
||||
(((field64 & 0xFF00000000000000ULL) >> 8) | (field64 & 0xFF00000000ULL) |
|
||||
((field64 & 0xFF00ULL) << 8) | ((field32 & 0xFF0000ULL) >> 16) | alphaMask);
|
||||
((PNGU_u64 *) buffer)[blockbase+5] =
|
||||
(((field64 & 0xFFFF0000000000ULL) << 8) | ((field64 & 0xFFFF0000ULL) << 16) |
|
||||
((field64 & 0xFFULL) << 24) | ((field32 & 0xFF000000ULL) >> 8) | (field32 & 0xFFFFULL));
|
||||
|
||||
field64 = *((PNGU_u64 *)(ctx->row_pointers[y4+2]+x12));
|
||||
field32 = (PNGU_u64) *((PNGU_u32 *)(ctx->row_pointers[y4+2]+x12+8));
|
||||
((PNGU_u64 *) buffer)[blockbase+2] =
|
||||
(((field64 & 0xFF00000000000000ULL) >> 8) | (field64 & 0xFF00000000ULL) |
|
||||
((field64 & 0xFF00ULL) << 8) | ((field32 & 0xFF0000ULL) >> 16) | alphaMask);
|
||||
((PNGU_u64 *) buffer)[blockbase+6] =
|
||||
(((field64 & 0xFFFF0000000000ULL) << 8) | ((field64 & 0xFFFF0000ULL) << 16) |
|
||||
((field64 & 0xFFULL) << 24) | ((field32 & 0xFF000000ULL) >> 8) | (field32 & 0xFFFFULL));
|
||||
|
||||
field64 = *((PNGU_u64 *)(ctx->row_pointers[y4+3]+x12));
|
||||
field32 = (PNGU_u64) *((PNGU_u32 *)(ctx->row_pointers[y4+3]+x12+8));
|
||||
((PNGU_u64 *) buffer)[blockbase+3] =
|
||||
(((field64 & 0xFF00000000000000ULL) >> 8) | (field64 & 0xFF00000000ULL) |
|
||||
((field64 & 0xFF00ULL) << 8) | ((field32 & 0xFF0000ULL) >> 16) | alphaMask);
|
||||
((PNGU_u64 *) buffer)[blockbase+7] =
|
||||
(((field64 & 0xFFFF0000000000ULL) << 8) | ((field64 & 0xFFFF0000ULL) << 16) |
|
||||
((field64 & 0xFFULL) << 24) | ((field32 & 0xFF000000ULL) >> 8) | (field32 & 0xFFFFULL));
|
||||
}
|
||||
}
|
||||
|
||||
// Free resources
|
||||
free (ctx->img_data);
|
||||
free (ctx->row_pointers);
|
||||
|
||||
// Success
|
||||
return PNGU_OK;
|
||||
}
|
||||
|
||||
int PNGU_EncodeFromRGB (IMGCTX ctx, PNGU_u32 width, PNGU_u32 height, void *buffer, PNGU_u32 stride)
|
||||
{
|
||||
png_uint_32 rowbytes;
|
||||
PNGU_u32 y;
|
||||
|
||||
// Erase from the context any readed info
|
||||
pngu_free_info (ctx);
|
||||
ctx->propRead = 0;
|
||||
|
||||
// Check if the user has selected a file to write the image
|
||||
if (ctx->source == PNGU_SOURCE_BUFFER);
|
||||
|
||||
else if (ctx->source == PNGU_SOURCE_DEVICE)
|
||||
{
|
||||
// Open file
|
||||
if (!(ctx->fd = fopen (ctx->filename, "wb")))
|
||||
return PNGU_CANT_OPEN_FILE;
|
||||
}
|
||||
|
||||
else
|
||||
return PNGU_NO_FILE_SELECTED;
|
||||
|
||||
// Allocation of libpng structs
|
||||
ctx->png_ptr = png_create_write_struct (PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
|
||||
if (!(ctx->png_ptr))
|
||||
if (ctx->infoRead)
|
||||
{
|
||||
if (ctx->source == PNGU_SOURCE_DEVICE)
|
||||
fclose (ctx->fd);
|
||||
return PNGU_LIB_ERROR;
|
||||
|
||||
png_destroy_read_struct (&(ctx->png_ptr), &(ctx->info_ptr), (png_infopp)NULL);
|
||||
|
||||
ctx->infoRead = 0;
|
||||
}
|
||||
|
||||
ctx->info_ptr = png_create_info_struct (ctx->png_ptr);
|
||||
if (!(ctx->info_ptr))
|
||||
{
|
||||
png_destroy_write_struct (&(ctx->png_ptr), (png_infopp)NULL);
|
||||
if (ctx->source == PNGU_SOURCE_DEVICE)
|
||||
fclose (ctx->fd);
|
||||
return PNGU_LIB_ERROR;
|
||||
}
|
||||
|
||||
if (ctx->source == PNGU_SOURCE_BUFFER)
|
||||
{
|
||||
// Installation of our custom data writer function
|
||||
ctx->cursor = 0;
|
||||
png_set_write_fn (ctx->png_ptr, ctx, pngu_write_data_to_buffer, pngu_flush_data_to_buffer);
|
||||
}
|
||||
else if (ctx->source == PNGU_SOURCE_DEVICE)
|
||||
{
|
||||
// Default data writer uses function fwrite, so it needs to use our FILE*
|
||||
png_init_io (ctx->png_ptr, ctx->fd);
|
||||
}
|
||||
|
||||
// Setup output file properties
|
||||
png_set_IHDR (ctx->png_ptr, ctx->info_ptr, width, height, 8, PNG_COLOR_TYPE_RGB,
|
||||
PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
|
||||
|
||||
// Allocate memory to store the image in RGB format
|
||||
rowbytes = width * 3;
|
||||
if (rowbytes % 4)
|
||||
rowbytes = ((rowbytes >>2) + 1) <<2; // Add extra padding so each row starts in a 4 byte boundary
|
||||
|
||||
ctx->img_data = malloc(rowbytes * height);
|
||||
memset(ctx->img_data, 0, rowbytes * height);
|
||||
|
||||
if (!ctx->img_data)
|
||||
{
|
||||
png_destroy_write_struct (&(ctx->png_ptr), (png_infopp)NULL);
|
||||
if (ctx->source == PNGU_SOURCE_DEVICE)
|
||||
fclose (ctx->fd);
|
||||
return PNGU_LIB_ERROR;
|
||||
}
|
||||
|
||||
ctx->row_pointers = malloc (sizeof (png_bytep) * height);
|
||||
memset(ctx->row_pointers, 0, sizeof (png_bytep) * height);
|
||||
|
||||
if (!ctx->row_pointers)
|
||||
{
|
||||
png_destroy_write_struct (&(ctx->png_ptr), (png_infopp)NULL);
|
||||
if (ctx->source == PNGU_SOURCE_DEVICE)
|
||||
fclose (ctx->fd);
|
||||
return PNGU_LIB_ERROR;
|
||||
}
|
||||
|
||||
for (y = 0; y < height; ++y)
|
||||
{
|
||||
ctx->row_pointers[y] = buffer + (y * rowbytes);
|
||||
}
|
||||
|
||||
// Tell libpng where is our image data
|
||||
png_set_rows (ctx->png_ptr, ctx->info_ptr, ctx->row_pointers);
|
||||
|
||||
// Write file header and image data
|
||||
png_write_png (ctx->png_ptr, ctx->info_ptr, PNG_TRANSFORM_IDENTITY, NULL);
|
||||
|
||||
// Tell libpng we have no more data to write
|
||||
png_write_end (ctx->png_ptr, (png_infop) NULL);
|
||||
|
||||
// Free resources
|
||||
free (ctx->img_data);
|
||||
free (ctx->row_pointers);
|
||||
png_destroy_write_struct (&(ctx->png_ptr), &(ctx->info_ptr));
|
||||
if (ctx->source == PNGU_SOURCE_DEVICE)
|
||||
fclose (ctx->fd);
|
||||
|
||||
// Success
|
||||
return ctx->cursor;
|
||||
}
|
||||
|
||||
int PNGU_EncodeFromGXTexture (IMGCTX ctx, PNGU_u32 width, PNGU_u32 height, void *buffer, PNGU_u32 stride)
|
||||
// Custom data provider function used for reading from memory buffers.
|
||||
static void pngu_read_data_from_buffer (png_structp png_ptr, png_bytep data, png_size_t length)
|
||||
{
|
||||
int res;
|
||||
PNGU_u32 x,y, tmpy1, tmpy2, tmpyWid, tmpxy;
|
||||
|
||||
unsigned char * ptr = (unsigned char*)buffer;
|
||||
unsigned char * tmpbuffer = (unsigned char *)malloc(width*height*3);
|
||||
memset(tmpbuffer, 0, width*height*3);
|
||||
png_uint_32 offset;
|
||||
|
||||
for(y=0; y < height; y++)
|
||||
{
|
||||
tmpy1 = y * 640*3;
|
||||
tmpy2 = y%4 << 2;
|
||||
tmpyWid = (((y >> 2)<<4)*width);
|
||||
|
||||
for(x=0; x < width; x++)
|
||||
{
|
||||
offset = tmpyWid + ((x >> 2)<<6) + ((tmpy2+ x%4 ) << 1);
|
||||
tmpxy = x * 3 + tmpy1;
|
||||
|
||||
tmpbuffer[tmpxy ] = ptr[offset+1]; // R
|
||||
tmpbuffer[tmpxy+1] = ptr[offset+32]; // G
|
||||
tmpbuffer[tmpxy+2] = ptr[offset+33]; // B
|
||||
}
|
||||
}
|
||||
|
||||
res = PNGU_EncodeFromRGB (ctx, width, height, tmpbuffer, stride);
|
||||
free(tmpbuffer);
|
||||
return res;
|
||||
IMGCTX ctx = (IMGCTX) png_get_io_ptr (png_ptr);
|
||||
memcpy (data, ctx->buffer + ctx->cursor, length);
|
||||
ctx->cursor += length;
|
||||
}
|
||||
|
||||
int pngu_info (IMGCTX ctx)
|
||||
// Custom data writer function used for writing to memory buffers.
|
||||
static void pngu_write_data_to_buffer (png_structp png_ptr, png_bytep data, png_size_t length)
|
||||
{
|
||||
IMGCTX ctx = (IMGCTX) png_get_io_ptr (png_ptr);
|
||||
memcpy (ctx->buffer + ctx->cursor, data, length);
|
||||
ctx->cursor += length;
|
||||
}
|
||||
|
||||
// Custom data flusher function used for writing to memory buffers.
|
||||
static void pngu_flush_data_to_buffer (png_structp png_ptr)
|
||||
{
|
||||
// Nothing to do here
|
||||
}
|
||||
|
||||
static int pngu_info (IMGCTX ctx)
|
||||
{
|
||||
png_byte magic[8];
|
||||
png_uint_32 width;
|
||||
@ -604,7 +294,7 @@ int pngu_info (IMGCTX ctx)
|
||||
return PNGU_OK;
|
||||
}
|
||||
|
||||
int pngu_decode (IMGCTX ctx, PNGU_u32 width, PNGU_u32 height, PNGU_u32 stripAlpha)
|
||||
static int pngu_decode (IMGCTX ctx, PNGU_u32 width, PNGU_u32 height, PNGU_u32 stripAlpha)
|
||||
{
|
||||
png_uint_32 rowbytes;
|
||||
png_uint_32 i, propImgHeight;
|
||||
@ -679,48 +369,313 @@ int pngu_decode (IMGCTX ctx, PNGU_u32 width, PNGU_u32 height, PNGU_u32 stripAlph
|
||||
return PNGU_OK;
|
||||
}
|
||||
|
||||
void pngu_free_info (IMGCTX ctx)
|
||||
static inline PNGU_u32 coordsRGBA8(PNGU_u32 x, PNGU_u32 y, PNGU_u32 w)
|
||||
{
|
||||
if (ctx->infoRead)
|
||||
return ((((y >> 2) * (w >> 2) + (x >> 2)) << 5) + ((y & 3) << 2) + (x & 3)) << 1;
|
||||
}
|
||||
|
||||
static PNGU_u8 * PNGU_DecodeTo4x4RGBA8 (IMGCTX ctx, PNGU_u32 width, PNGU_u32 height, PNGU_u8 default_alpha)
|
||||
{
|
||||
PNGU_u8 *dst;
|
||||
PNGU_u32 x, y, offset;
|
||||
png_byte *pixel;
|
||||
|
||||
if (pngu_decode (ctx, width, height, 0) != PNGU_OK)
|
||||
return NULL;
|
||||
|
||||
PNGU_u32 newWidth = width;
|
||||
if(newWidth%4) newWidth += (4-newWidth%4);
|
||||
PNGU_u32 newHeight = height;
|
||||
if(newHeight%4) newHeight += (4-newHeight%4);
|
||||
|
||||
int len = (newWidth * newHeight) << 2;
|
||||
if(len%32) len += (32-len%32);
|
||||
dst = memalign (32, len);
|
||||
|
||||
if(!dst)
|
||||
return NULL;
|
||||
|
||||
for (y = 0; y < newHeight; y++)
|
||||
{
|
||||
for (x = 0; x < newWidth; x++)
|
||||
{
|
||||
offset = coordsRGBA8(x, y, newWidth);
|
||||
|
||||
if(y >= height || x >= width)
|
||||
{
|
||||
dst[offset] = 0;
|
||||
dst[offset+1] = 255;
|
||||
dst[offset+32] = 255;
|
||||
dst[offset+33] = 255;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (ctx->prop.imgColorType == PNGU_COLOR_TYPE_GRAY_ALPHA ||
|
||||
ctx->prop.imgColorType == PNGU_COLOR_TYPE_RGB_ALPHA)
|
||||
{
|
||||
pixel = &(ctx->row_pointers[y][x*4]);
|
||||
dst[offset] = pixel[3]; // Alpha
|
||||
dst[offset+1] = pixel[0]; // Red
|
||||
dst[offset+32] = pixel[1]; // Green
|
||||
dst[offset+33] = pixel[2]; // Blue
|
||||
}
|
||||
else
|
||||
{
|
||||
pixel = &(ctx->row_pointers[y][x*3]);
|
||||
dst[offset] = default_alpha; // Alpha
|
||||
dst[offset+1] = pixel[0]; // Red
|
||||
dst[offset+32] = pixel[1]; // Green
|
||||
dst[offset+33] = pixel[2]; // Blue
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Free resources
|
||||
free (ctx->img_data);
|
||||
free (ctx->row_pointers);
|
||||
|
||||
DCFlushRange(dst, len);
|
||||
return dst;
|
||||
}
|
||||
|
||||
IMGCTX PNGU_SelectImageFromBuffer (const void *buffer)
|
||||
{
|
||||
IMGCTX ctx = NULL;
|
||||
|
||||
if (!buffer)
|
||||
return NULL;
|
||||
|
||||
ctx = malloc (sizeof (struct _IMGCTX));
|
||||
if (!ctx)
|
||||
return NULL;
|
||||
|
||||
ctx->buffer = (void *) buffer;
|
||||
ctx->source = PNGU_SOURCE_BUFFER;
|
||||
ctx->cursor = 0;
|
||||
ctx->filename = NULL;
|
||||
ctx->propRead = 0;
|
||||
ctx->infoRead = 0;
|
||||
|
||||
return ctx;
|
||||
}
|
||||
|
||||
IMGCTX PNGU_SelectImageFromDevice (const char *filename)
|
||||
{
|
||||
IMGCTX ctx = NULL;
|
||||
|
||||
if (!filename)
|
||||
return NULL;
|
||||
|
||||
ctx = malloc (sizeof (struct _IMGCTX));
|
||||
if (!ctx)
|
||||
return NULL;
|
||||
|
||||
ctx->buffer = NULL;
|
||||
ctx->source = PNGU_SOURCE_DEVICE;
|
||||
ctx->cursor = 0;
|
||||
|
||||
ctx->filename = malloc (strlen (filename) + 1);
|
||||
if (!ctx->filename)
|
||||
{
|
||||
free (ctx);
|
||||
return NULL;
|
||||
}
|
||||
strcpy(ctx->filename, filename);
|
||||
|
||||
ctx->propRead = 0;
|
||||
ctx->infoRead = 0;
|
||||
|
||||
return ctx;
|
||||
}
|
||||
|
||||
void PNGU_ReleaseImageContext (IMGCTX ctx)
|
||||
{
|
||||
if (!ctx)
|
||||
return;
|
||||
|
||||
if (ctx->filename)
|
||||
free (ctx->filename);
|
||||
|
||||
if ((ctx->propRead) && (ctx->prop.trans))
|
||||
free (ctx->prop.trans);
|
||||
|
||||
pngu_free_info (ctx);
|
||||
free (ctx);
|
||||
}
|
||||
|
||||
int PNGU_GetImageProperties (IMGCTX ctx, PNGUPROP *imgprop)
|
||||
{
|
||||
int res;
|
||||
|
||||
if (!ctx->propRead)
|
||||
{
|
||||
res = pngu_info (ctx);
|
||||
if (res != PNGU_OK)
|
||||
return res;
|
||||
}
|
||||
|
||||
*imgprop = ctx->prop;
|
||||
return PNGU_OK;
|
||||
}
|
||||
|
||||
PNGU_u8 * DecodePNG(const PNGU_u8 *src, int * width, int * height)
|
||||
{
|
||||
PNGUPROP imgProp;
|
||||
IMGCTX ctx = PNGU_SelectImageFromBuffer(src);
|
||||
PNGU_u8 *dst = NULL;
|
||||
|
||||
if(!ctx)
|
||||
return NULL;
|
||||
|
||||
if(PNGU_GetImageProperties(ctx, &imgProp) == PNGU_OK)
|
||||
{
|
||||
dst = PNGU_DecodeTo4x4RGBA8 (ctx, imgProp.imgWidth, imgProp.imgHeight, 255);
|
||||
|
||||
*width = imgProp.imgWidth;
|
||||
*height = imgProp.imgHeight;
|
||||
}
|
||||
|
||||
PNGU_ReleaseImageContext (ctx);
|
||||
return dst;
|
||||
}
|
||||
|
||||
int PNGU_EncodeFromRGB (IMGCTX ctx, PNGU_u32 width, PNGU_u32 height, void *buffer, PNGU_u32 stride)
|
||||
{
|
||||
png_uint_32 rowbytes;
|
||||
PNGU_u32 y;
|
||||
|
||||
// Erase from the context any readed info
|
||||
pngu_free_info (ctx);
|
||||
ctx->propRead = 0;
|
||||
|
||||
// Check if the user has selected a file to write the image
|
||||
if (ctx->source == PNGU_SOURCE_BUFFER);
|
||||
|
||||
else if (ctx->source == PNGU_SOURCE_DEVICE)
|
||||
{
|
||||
// Open file
|
||||
if (!(ctx->fd = fopen (ctx->filename, "wb")))
|
||||
return PNGU_CANT_OPEN_FILE;
|
||||
}
|
||||
|
||||
else
|
||||
return PNGU_NO_FILE_SELECTED;
|
||||
|
||||
// Allocation of libpng structs
|
||||
ctx->png_ptr = png_create_write_struct (PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
|
||||
if (!(ctx->png_ptr))
|
||||
{
|
||||
if (ctx->source == PNGU_SOURCE_DEVICE)
|
||||
fclose (ctx->fd);
|
||||
|
||||
png_destroy_read_struct (&(ctx->png_ptr), &(ctx->info_ptr), (png_infopp)NULL);
|
||||
|
||||
ctx->infoRead = 0;
|
||||
return PNGU_LIB_ERROR;
|
||||
}
|
||||
|
||||
ctx->info_ptr = png_create_info_struct (ctx->png_ptr);
|
||||
if (!(ctx->info_ptr))
|
||||
{
|
||||
png_destroy_write_struct (&(ctx->png_ptr), (png_infopp)NULL);
|
||||
if (ctx->source == PNGU_SOURCE_DEVICE)
|
||||
fclose (ctx->fd);
|
||||
return PNGU_LIB_ERROR;
|
||||
}
|
||||
|
||||
if (ctx->source == PNGU_SOURCE_BUFFER)
|
||||
{
|
||||
// Installation of our custom data writer function
|
||||
ctx->cursor = 0;
|
||||
png_set_write_fn (ctx->png_ptr, ctx, pngu_write_data_to_buffer, pngu_flush_data_to_buffer);
|
||||
}
|
||||
else if (ctx->source == PNGU_SOURCE_DEVICE)
|
||||
{
|
||||
// Default data writer uses function fwrite, so it needs to use our FILE*
|
||||
png_init_io (ctx->png_ptr, ctx->fd);
|
||||
}
|
||||
|
||||
// Setup output file properties
|
||||
png_set_IHDR (ctx->png_ptr, ctx->info_ptr, width, height, 8, PNG_COLOR_TYPE_RGB,
|
||||
PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
|
||||
|
||||
// Allocate memory to store the image in RGB format
|
||||
rowbytes = width * 3;
|
||||
if (rowbytes % 4)
|
||||
rowbytes = ((rowbytes >>2) + 1) <<2; // Add extra padding so each row starts in a 4 byte boundary
|
||||
|
||||
ctx->img_data = malloc(rowbytes * height);
|
||||
memset(ctx->img_data, 0, rowbytes * height);
|
||||
|
||||
if (!ctx->img_data)
|
||||
{
|
||||
png_destroy_write_struct (&(ctx->png_ptr), (png_infopp)NULL);
|
||||
if (ctx->source == PNGU_SOURCE_DEVICE)
|
||||
fclose (ctx->fd);
|
||||
return PNGU_LIB_ERROR;
|
||||
}
|
||||
|
||||
ctx->row_pointers = malloc (sizeof (png_bytep) * height);
|
||||
memset(ctx->row_pointers, 0, sizeof (png_bytep) * height);
|
||||
|
||||
if (!ctx->row_pointers)
|
||||
{
|
||||
png_destroy_write_struct (&(ctx->png_ptr), (png_infopp)NULL);
|
||||
if (ctx->source == PNGU_SOURCE_DEVICE)
|
||||
fclose (ctx->fd);
|
||||
return PNGU_LIB_ERROR;
|
||||
}
|
||||
|
||||
for (y = 0; y < height; ++y)
|
||||
{
|
||||
ctx->row_pointers[y] = buffer + (y * rowbytes);
|
||||
}
|
||||
|
||||
// Tell libpng where is our image data
|
||||
png_set_rows (ctx->png_ptr, ctx->info_ptr, ctx->row_pointers);
|
||||
|
||||
// Write file header and image data
|
||||
png_write_png (ctx->png_ptr, ctx->info_ptr, PNG_TRANSFORM_IDENTITY, NULL);
|
||||
|
||||
// Tell libpng we have no more data to write
|
||||
png_write_end (ctx->png_ptr, (png_infop) NULL);
|
||||
|
||||
// Free resources
|
||||
free (ctx->img_data);
|
||||
free (ctx->row_pointers);
|
||||
png_destroy_write_struct (&(ctx->png_ptr), &(ctx->info_ptr));
|
||||
if (ctx->source == PNGU_SOURCE_DEVICE)
|
||||
fclose (ctx->fd);
|
||||
|
||||
// Success
|
||||
return ctx->cursor;
|
||||
}
|
||||
|
||||
// Custom data provider function used for reading from memory buffers.
|
||||
void pngu_read_data_from_buffer (png_structp png_ptr, png_bytep data, png_size_t length)
|
||||
int PNGU_EncodeFromGXTexture (IMGCTX ctx, PNGU_u32 width, PNGU_u32 height, void *buffer, PNGU_u32 stride)
|
||||
{
|
||||
IMGCTX ctx = (IMGCTX) png_get_io_ptr (png_ptr);
|
||||
memcpy (data, ctx->buffer + ctx->cursor, length);
|
||||
ctx->cursor += length;
|
||||
}
|
||||
int res;
|
||||
PNGU_u32 x,y, tmpy1, tmpy2, tmpyWid, tmpxy;
|
||||
|
||||
// Custom data writer function used for writing to memory buffers.
|
||||
void pngu_write_data_to_buffer (png_structp png_ptr, png_bytep data, png_size_t length)
|
||||
{
|
||||
IMGCTX ctx = (IMGCTX) png_get_io_ptr (png_ptr);
|
||||
memcpy (ctx->buffer + ctx->cursor, data, length);
|
||||
ctx->cursor += length;
|
||||
}
|
||||
unsigned char * ptr = (unsigned char*)buffer;
|
||||
unsigned char * tmpbuffer = (unsigned char *)malloc(width*height*3);
|
||||
memset(tmpbuffer, 0, width*height*3);
|
||||
png_uint_32 offset;
|
||||
|
||||
for(y=0; y < height; y++)
|
||||
{
|
||||
tmpy1 = y * 640*3;
|
||||
tmpy2 = y%4 << 2;
|
||||
tmpyWid = (((y >> 2)<<4)*width);
|
||||
|
||||
// Custom data flusher function used for writing to memory buffers.
|
||||
void pngu_flush_data_to_buffer (png_structp png_ptr)
|
||||
{
|
||||
// Nothing to do here
|
||||
}
|
||||
for(x=0; x < width; x++)
|
||||
{
|
||||
offset = tmpyWid + ((x >> 2)<<6) + ((tmpy2+ x%4 ) << 1);
|
||||
tmpxy = x * 3 + tmpy1;
|
||||
|
||||
// Function used in YCbYCr to RGB decoding
|
||||
int pngu_clamp (int value, int min, int max)
|
||||
{
|
||||
if (value < min)
|
||||
value = min;
|
||||
else if (value > max)
|
||||
value = max;
|
||||
|
||||
return value;
|
||||
tmpbuffer[tmpxy ] = ptr[offset+1]; // R
|
||||
tmpbuffer[tmpxy+1] = ptr[offset+32]; // G
|
||||
tmpbuffer[tmpxy+2] = ptr[offset+33]; // B
|
||||
}
|
||||
}
|
||||
|
||||
res = PNGU_EncodeFromRGB (ctx, width, height, tmpbuffer, stride);
|
||||
free(tmpbuffer);
|
||||
return res;
|
||||
}
|
||||
|
@ -1,38 +1,15 @@
|
||||
/********************************************************************************************
|
||||
|
||||
PNGU Version : 0.2a
|
||||
|
||||
Coder : frontier
|
||||
|
||||
More info : http://frontier-dev.net
|
||||
|
||||
Modified by Tantric, 2009
|
||||
|
||||
*
|
||||
* PNGU
|
||||
*
|
||||
* Original author: frontier (http://frontier-dev.net)
|
||||
* Modified by Tantric, 2009-2010
|
||||
*
|
||||
********************************************************************************************/
|
||||
|
||||
#ifndef __PNGU__
|
||||
#define __PNGU__
|
||||
|
||||
// Return codes
|
||||
#define PNGU_OK 0
|
||||
#define PNGU_ODD_WIDTH 1
|
||||
#define PNGU_ODD_STRIDE 2
|
||||
#define PNGU_INVALID_WIDTH_OR_HEIGHT 3
|
||||
#define PNGU_FILE_IS_NOT_PNG 4
|
||||
#define PNGU_UNSUPPORTED_COLOR_TYPE 5
|
||||
#define PNGU_NO_FILE_SELECTED 6
|
||||
#define PNGU_CANT_OPEN_FILE 7
|
||||
#define PNGU_CANT_READ_FILE 8
|
||||
#define PNGU_LIB_ERROR 9
|
||||
|
||||
// Color types
|
||||
#define PNGU_COLOR_TYPE_GRAY 1
|
||||
#define PNGU_COLOR_TYPE_GRAY_ALPHA 2
|
||||
#define PNGU_COLOR_TYPE_PALETTE 3
|
||||
#define PNGU_COLOR_TYPE_RGB 4
|
||||
#define PNGU_COLOR_TYPE_RGB_ALPHA 5
|
||||
#define PNGU_COLOR_TYPE_UNKNOWN 6
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
@ -67,7 +44,7 @@ struct _IMGCTX;
|
||||
typedef struct _IMGCTX *IMGCTX;
|
||||
|
||||
/****************************************************************************
|
||||
* Image context handling *
|
||||
* Image context handling *
|
||||
****************************************************************************/
|
||||
|
||||
// Selects a PNG file, previosly loaded into a buffer, and creates an image context for subsequent procesing.
|
||||
@ -79,22 +56,18 @@ IMGCTX PNGU_SelectImageFromDevice (const char *filename);
|
||||
// Frees resources associated with an image context. Always call this function when you no longer need the IMGCTX.
|
||||
void PNGU_ReleaseImageContext (IMGCTX ctx);
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
* Miscelaneous *
|
||||
* Miscellaneous *
|
||||
****************************************************************************/
|
||||
|
||||
// Retrieves info from selected PNG file, including image dimensions, color format, background and transparency colors.
|
||||
int PNGU_GetImageProperties (IMGCTX ctx, PNGUPROP *fileproperties);
|
||||
|
||||
/****************************************************************************
|
||||
* Image conversion *
|
||||
* Image conversion *
|
||||
****************************************************************************/
|
||||
|
||||
// Expands selected image into a 4x4 tiled RGBA8 buffer. You need to specify context, image dimensions,
|
||||
// destination address and default alpha value, which is used if the source image doesn't have an alpha channel.
|
||||
int PNGU_DecodeTo4x4RGBA8 (IMGCTX ctx, PNGU_u32 width, PNGU_u32 height, void *buffer, PNGU_u8 default_alpha);
|
||||
|
||||
PNGU_u8 * DecodePNG(const PNGU_u8 *src, int *width, int *height);
|
||||
int PNGU_EncodeFromRGB (IMGCTX ctx, PNGU_u32 width, PNGU_u32 height, void *buffer, PNGU_u32 stride);
|
||||
int PNGU_EncodeFromGXTexture (IMGCTX ctx, PNGU_u32 width, PNGU_u32 height, void *buffer, PNGU_u32 stride);
|
||||
|
||||
@ -103,4 +76,3 @@ int PNGU_EncodeFromGXTexture (IMGCTX ctx, PNGU_u32 width, PNGU_u32 height, void
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user