mirror of
https://github.com/dborth/snes9xgx.git
synced 2024-11-24 03:29:22 +01:00
new font, rewritten PNGU, menu tweaks, optimized text code
This commit is contained in:
parent
a126568d04
commit
3b8b7b74d1
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();
|
||||
}
|
||||
|
@ -1,23 +1,53 @@
|
||||
msgid " "
|
||||
msgstr " "
|
||||
|
||||
msgid "&"
|
||||
msgstr "&"
|
||||
|
||||
msgid "16:9 Correction"
|
||||
msgstr "Correction 16:9"
|
||||
|
||||
msgid "7z decompression failed: Archive contains too many files"
|
||||
msgstr "La décompression 7z a échoué : l'archive contient trop de fichiers"
|
||||
|
||||
msgid "7z decompression failed: Failed to read file data"
|
||||
msgstr "La décompression 7z a échoué : la lecture des données du fichier a échoué"
|
||||
|
||||
msgid "7z decompression failed: File is corrupt"
|
||||
msgstr "La décompression 7z a échoué : le fichier est corrompu"
|
||||
|
||||
msgid "7z decompression failed: File is corrupt (CRC mismatch)"
|
||||
msgstr "La décompression 7z a échoué : le fichier est corrompu (erreur de contrôle de redondance cyclique - CRC)"
|
||||
|
||||
msgid "7z decompression failed: File uses too high of compression settings (dictionary size is too large)"
|
||||
msgstr "La décompression 7z a échoué : le fichier utilise un paramètre de compression trop élevé (taille du dictionnaire trop haute)"
|
||||
|
||||
msgid "7z decompression failed: File uses unsupported compression settings"
|
||||
msgstr "La décompression 7z a échoué : le fichier utilise des paramètres de compression non supportés"
|
||||
|
||||
msgid "A (Rapid)"
|
||||
msgstr "A (Rapide)"
|
||||
|
||||
msgid "Aim Offscreen"
|
||||
msgstr "Visée hors champ"
|
||||
|
||||
msgid "An update is available!"
|
||||
msgstr "Une mise à jour est disponible!"
|
||||
msgstr "Une mise à jour est disponible !"
|
||||
|
||||
msgid "Are you sure that you want to reset this game? Any unsaved progress will be lost."
|
||||
msgstr "Êtes-vous sûr de vouloir redémarrer ce jeu ? Toute progression non sauvegardée sera perdue."
|
||||
|
||||
msgid "Are you sure that you want to reset your mappings?"
|
||||
msgstr "Êtes-vous sûr de vouloir réinitialiser les touches?"
|
||||
msgstr "Êtes-vous sûr de vouloir réinitialiser les touches ?"
|
||||
|
||||
msgid "Are you sure that you want to reset your settings?"
|
||||
msgstr "Êtes-vous sûr de vouloir réinitialiser les paramètres?"
|
||||
msgstr "Êtes-vous sûr de vouloir réinitialiser tout les paramètres ?"
|
||||
|
||||
msgid "Maintain Aspect Ratio"
|
||||
msgstr "Conserver les proportions"
|
||||
|
||||
msgid "Attempting to determine load device..."
|
||||
msgstr "Tentative de détection du périphérique d'entrée..."
|
||||
|
||||
msgid "Attempting to determine save device..."
|
||||
msgstr "Tentative de détection du périphérique de sauvegarde..."
|
||||
|
||||
msgid "Auto"
|
||||
msgstr "Auto"
|
||||
@ -34,6 +64,9 @@ msgstr "Sauvegarde Auto"
|
||||
msgid "Automatic (Recommended)"
|
||||
msgstr "Automatique (Recommandé)"
|
||||
|
||||
msgid "B (Rapid)"
|
||||
msgstr "B (Rapide)"
|
||||
|
||||
msgid "Back"
|
||||
msgstr "Retour"
|
||||
|
||||
@ -56,7 +89,7 @@ msgid "Cheats"
|
||||
msgstr "Cheats"
|
||||
|
||||
msgid "Cheats file not found!"
|
||||
msgstr "Fichier Cheats non trouvé!"
|
||||
msgstr "Fichier Cheats non trouvé !"
|
||||
|
||||
msgid "Cheats Folder"
|
||||
msgstr "Dossier Cheats"
|
||||
@ -74,7 +107,13 @@ msgid "Coding"
|
||||
msgstr "Programmation"
|
||||
|
||||
msgid "Coding & menu design"
|
||||
msgstr "Program. & design du menu"
|
||||
msgstr "Prog. & design du menu"
|
||||
|
||||
msgid "Compressed GBA files are not supported!"
|
||||
msgstr "Les fichiers GBA compressés ne sont pas supportés !"
|
||||
|
||||
msgid "Connecting to network share..."
|
||||
msgstr "Connection au partage réseau en cours..."
|
||||
|
||||
msgid "Controller"
|
||||
msgstr "Contrôleur"
|
||||
@ -88,12 +127,30 @@ msgstr "Dossier des jaquettes"
|
||||
msgid "Credits"
|
||||
msgstr "Crédits"
|
||||
|
||||
msgid "Cropping"
|
||||
msgstr "Recadrage"
|
||||
|
||||
msgid "Crosshair"
|
||||
msgstr "Réticule de visée"
|
||||
|
||||
msgid "Cursor"
|
||||
msgstr "Curseur"
|
||||
|
||||
msgid "Data DVD"
|
||||
msgstr "Données DVD"
|
||||
|
||||
msgid "Default"
|
||||
msgstr "Par défaut"
|
||||
|
||||
msgid "Directory name is too long!"
|
||||
msgstr "Le nom du répertoire est trop long !"
|
||||
|
||||
msgid "Disabled"
|
||||
msgstr "Désactivé"
|
||||
|
||||
msgid "DISABLED"
|
||||
msgstr "DÉSACTIVÉ"
|
||||
|
||||
msgid "distributed, or modified under the terms of the"
|
||||
msgstr "distribuée, ou modifiée selon les termes de"
|
||||
|
||||
@ -106,17 +163,65 @@ msgstr "Bas"
|
||||
msgid "DOWN"
|
||||
msgstr "BAS"
|
||||
|
||||
msgid "Downloading..."
|
||||
msgstr "Téléchargement en cours..."
|
||||
|
||||
msgid "Dutch"
|
||||
msgstr "Néerlandais"
|
||||
|
||||
msgid "Empty or invalid ZIP file!"
|
||||
msgstr "Fichier ZIP vide ou invalide !"
|
||||
|
||||
msgid "Enabled"
|
||||
msgstr "Activé"
|
||||
|
||||
msgid "ENABLED"
|
||||
msgstr "ACTIVÉ"
|
||||
|
||||
msgid "English"
|
||||
msgstr "Anglais"
|
||||
|
||||
msgid "Error"
|
||||
msgstr "Erreur"
|
||||
|
||||
msgid "Error - Invalid ZIP file!"
|
||||
msgstr "Erreur - Fichier ZIP invalide !"
|
||||
|
||||
msgid "Error creating file!"
|
||||
msgstr "Une erreur est survenue à la création du fichier !"
|
||||
|
||||
msgid "Error loading game!"
|
||||
msgstr "Erreur de chargement du jeu !"
|
||||
|
||||
msgid "Error opening archive!"
|
||||
msgstr "Erreur lors de l'ouverture de l'archive !"
|
||||
|
||||
msgid "Error opening directory!"
|
||||
msgstr "Erreur lors de l'ouverture du répertoire !"
|
||||
|
||||
msgid "Error opening file!"
|
||||
msgstr "Erreur lors de l'ouverture du fichier !"
|
||||
|
||||
msgid "Error reading file!"
|
||||
msgstr "Une erreur est survenue à la lecture du fichier !"
|
||||
|
||||
msgid "Error saving file!"
|
||||
msgstr "Erreur lors de la sauvegarde du fichier !"
|
||||
|
||||
msgid "Exit"
|
||||
msgstr "Sortir"
|
||||
|
||||
msgid "Exit Action"
|
||||
msgstr "Sortie de SNES9xGx"
|
||||
msgstr "Sortie de l'émulateur"
|
||||
|
||||
msgid "Failed to connect to network share."
|
||||
msgstr "La connection au partage réseau a échoué."
|
||||
|
||||
msgid "FDS BIOS file is invalid!"
|
||||
msgstr "Le fichier du BIOS du FDS (Famicom Disk System) est invalide !"
|
||||
|
||||
msgid "FDS BIOS file not found!"
|
||||
msgstr "Le fichier du BIOS du FDS (Famicom Disk System) est introuvable !"
|
||||
|
||||
msgid "Filtered"
|
||||
msgstr "Filtré"
|
||||
@ -124,6 +229,18 @@ msgstr "Filtré"
|
||||
msgid "Filtering"
|
||||
msgstr "Filtrage"
|
||||
|
||||
msgid "Fire"
|
||||
msgstr "Tirer"
|
||||
|
||||
msgid "French"
|
||||
msgstr "Français"
|
||||
|
||||
msgid "GBA Screen Zoom"
|
||||
msgstr "Zoom écran GBA"
|
||||
|
||||
msgid "Game Genie ROM not found!"
|
||||
msgstr "La ROM Game Genie est introuvable !"
|
||||
|
||||
msgid "Game Settings"
|
||||
msgstr "Configuration"
|
||||
|
||||
@ -136,9 +253,21 @@ msgstr "Configuration - Cheats"
|
||||
msgid "Game Settings - Video"
|
||||
msgstr "Configuration - Vidéo"
|
||||
|
||||
msgid "Game Timing"
|
||||
msgstr "Timing du jeu"
|
||||
|
||||
msgid "Game Genie DISABLED"
|
||||
msgstr "Game Genie Désactivé"
|
||||
|
||||
msgid "Game Genie ENABLED"
|
||||
msgstr "Game Genie Activé"
|
||||
|
||||
msgid "GameCube Controller"
|
||||
msgstr "Manette Gamecube"
|
||||
|
||||
msgid "German"
|
||||
msgstr "Allemand"
|
||||
|
||||
msgid "GNU General Public License (GPL) Version 2."
|
||||
msgstr "la Licence Publique Générale (GPL) GNU Version 2."
|
||||
|
||||
@ -151,8 +280,56 @@ msgstr "Horizontal"
|
||||
msgid "Information"
|
||||
msgstr "Information"
|
||||
|
||||
msgid "Initializing network..."
|
||||
msgstr "Initialisation du réseau en cours..."
|
||||
|
||||
msgid "Insert Coin"
|
||||
msgstr "Insérer une pièce"
|
||||
|
||||
msgid "Insert Coin / Switch Disk"
|
||||
msgstr "Insér. une pièce/Chang. disq."
|
||||
|
||||
msgid "Invalid file size!"
|
||||
msgstr "Taille du fichier invalide"
|
||||
|
||||
msgid "Invalid game file!"
|
||||
msgstr "Taille du fichier du jeu invalide"
|
||||
|
||||
msgid "Invalid network settings - Check settings.xml."
|
||||
msgstr "Paramètres réseau invalides - Veuillez vérifier le fichier settings.xml."
|
||||
|
||||
msgid "Invalid network settings - Share IP is blank."
|
||||
msgstr "Paramètres réseau invalides - L'IP partagée n'est pas renseignée."
|
||||
|
||||
msgid "Invalid network settings - Share name is blank."
|
||||
msgstr "Paramètres réseau invalides - Le nom du partage n'est pas renseigné."
|
||||
|
||||
msgid "Invalid save file"
|
||||
msgstr "Fichier de sauvegarde invalide"
|
||||
|
||||
msgid "Invalid state file"
|
||||
msgstr "Fichier de sauvegarde d'état invalide"
|
||||
|
||||
msgid "Italian"
|
||||
msgstr "Italien"
|
||||
|
||||
msgid "Japanese"
|
||||
msgstr "Japonais"
|
||||
|
||||
msgid "Justifier"
|
||||
msgstr "Justifier"
|
||||
msgstr "Konami Justifier"
|
||||
|
||||
msgid "Justifier - GameCube Controller"
|
||||
msgstr "Konami Justifier - Manette GameCube"
|
||||
|
||||
msgid "Justifier - Wiimote"
|
||||
msgstr "Konami Justifier - Wiimote"
|
||||
|
||||
msgid "Korean"
|
||||
msgstr "Coréen"
|
||||
|
||||
msgid "L TRIG"
|
||||
msgstr "L"
|
||||
|
||||
msgid "Language"
|
||||
msgstr "Langage"
|
||||
@ -166,6 +343,9 @@ msgstr "Gauche"
|
||||
msgid "LEFT"
|
||||
msgstr "GAUCHE"
|
||||
|
||||
msgid "Left Button"
|
||||
msgstr "Clic gauche"
|
||||
|
||||
msgid "Load"
|
||||
msgstr "Charger"
|
||||
|
||||
@ -181,9 +361,24 @@ msgstr "Charger une partie"
|
||||
msgid "Loading"
|
||||
msgstr "Chargement"
|
||||
|
||||
msgid "Loading DVD..."
|
||||
msgstr "Chargement du DVD en cours..."
|
||||
|
||||
msgid "Loading patch..."
|
||||
msgstr "Chargement du patch en cours..."
|
||||
|
||||
msgid "Loading..."
|
||||
msgstr "Chargement en cours..."
|
||||
|
||||
msgid "Main Menu"
|
||||
msgstr "Menu Principal"
|
||||
|
||||
msgid "Match Wii Controls"
|
||||
msgstr "Jouabilité Wii identique"
|
||||
|
||||
msgid "Maximum filepath length reached!"
|
||||
msgid "La longueur maximale du chemin d'accés est atteinte !"
|
||||
|
||||
msgid "Menu"
|
||||
msgstr "Menu"
|
||||
|
||||
@ -202,21 +397,54 @@ msgstr "Volume de la Musique"
|
||||
msgid "Mute"
|
||||
msgstr "Muet"
|
||||
|
||||
msgid "NES Controller"
|
||||
msgstr "Manette NES"
|
||||
|
||||
msgid "NES Controllers (2)"
|
||||
msgstr "Manettes NES (2)"
|
||||
|
||||
msgid "NES Controllers (4)"
|
||||
msgstr "Manettes NES (4)"
|
||||
|
||||
msgid "NES Zapper"
|
||||
msgstr "Nintendo Zapper"
|
||||
|
||||
msgid "Network"
|
||||
msgstr "Réseau"
|
||||
|
||||
msgid "Network Share"
|
||||
msgstr "Partage réseau"
|
||||
|
||||
msgid "New"
|
||||
msgstr "Nouv."
|
||||
msgstr "Nouvelle"
|
||||
|
||||
msgid "New Snapshot"
|
||||
msgstr "Nouvelle sauvegarde d'état"
|
||||
|
||||
msgid "New SRAM"
|
||||
msgstr "Nouvelle sauvegarde SRAM"
|
||||
|
||||
msgid "No"
|
||||
msgstr "Non"
|
||||
msgstr "Non"
|
||||
|
||||
msgid "None"
|
||||
msgstr "Aucun"
|
||||
|
||||
msgid "No data to save!"
|
||||
msgstr "Pas de données (RAM) à sauvegarder !"
|
||||
|
||||
msgid "No disc inserted!"
|
||||
msgstr "Aucun disque inséré !"
|
||||
|
||||
msgid "No SRAM data to save!"
|
||||
msgstr "Pas de données SRAM à sauvegarder !"
|
||||
|
||||
|
||||
msgid "No game saves found."
|
||||
msgstr "Aucune sauvegarde trouvée."
|
||||
|
||||
msgid "None"
|
||||
|
||||
msgstr "Aucun"
|
||||
|
||||
msgid "NTSC (480i)"
|
||||
msgstr "NTSC (480i)"
|
||||
|
||||
@ -226,9 +454,15 @@ msgstr "Nunchuk"
|
||||
msgid "Off"
|
||||
msgstr "Off"
|
||||
|
||||
msgid "Official Site: http://code.google.com/p/fceugc/"
|
||||
msgstr "Site Officiel: http://code.google.com/p/fceugc/"
|
||||
|
||||
msgid "Official Site: http://code.google.com/p/snes9x-gx/"
|
||||
msgstr "Site Officiel: http://code.google.com/p/snes9x-gx/"
|
||||
|
||||
msgid "Official Site: http://code.google.com/p/vba-wii/"
|
||||
msgstr "Site Officiel: http://code.google.com/p/vba-wii/"
|
||||
|
||||
msgid "OK"
|
||||
msgstr "OK"
|
||||
|
||||
@ -238,20 +472,56 @@ msgstr "On"
|
||||
msgid "Original"
|
||||
msgstr "Original"
|
||||
|
||||
msgid "Out of memory!"
|
||||
msgstr "Mémoire insuffisante !"
|
||||
|
||||
msgid "Out of memory: too many files!"
|
||||
msgstr "Mémoire insuffisante : trop de fichiers !"
|
||||
|
||||
msgid "P 1"
|
||||
msgstr "J1"
|
||||
|
||||
msgid "P2"
|
||||
msgstr "J2"
|
||||
|
||||
msgid "P3"
|
||||
msgstr "J3"
|
||||
|
||||
msgid "P4"
|
||||
msgstr "J4"
|
||||
|
||||
msgid "PAL (50Hz)"
|
||||
msgstr "PAL (50Hz)"
|
||||
|
||||
msgid "PAL (60Hz)"
|
||||
msgstr "PAL (60Hz)"
|
||||
|
||||
msgid "Palette saved"
|
||||
msgstr "La palette est sauvegardée"
|
||||
|
||||
msgid "Partial Stretch"
|
||||
msgstr "Étirer partiellement"
|
||||
|
||||
msgid "Pause"
|
||||
msgstr "Pause"
|
||||
|
||||
msgid "Please install IOS 202 for DVD support."
|
||||
msgstr "Veuillez installer l'IOS 202 pour le support du DVD"
|
||||
|
||||
msgid "Please Wait"
|
||||
msgstr "Veuillez patienter"
|
||||
|
||||
msgid "PLUS"
|
||||
msgstr "PLUS"
|
||||
|
||||
msgid "Portuguese"
|
||||
msgstr "Portugais"
|
||||
|
||||
msgid "Power off Wii"
|
||||
msgstr "Eteindre la Wii"
|
||||
msgstr "Éteindre la Wii"
|
||||
|
||||
msgid "Preferences saved"
|
||||
msgstr "Les préférences ont été sauvegardés"
|
||||
|
||||
msgid "Press any button on the Classic Controller now. Press Home to clear the existing mapping."
|
||||
msgstr "Appuyer sur un bouton de la manette Classique. Appuyer sur HOME pour effacer le paramètre actuel."
|
||||
@ -277,6 +547,12 @@ msgstr "Quitter le Jeu"
|
||||
msgid "Quit this game? Any unsaved progress will be lost."
|
||||
msgstr "Quitter ce jeu ? Toute progression non sauvegardée sera perdue."
|
||||
|
||||
msgid "R TRIG"
|
||||
msgstr "R"
|
||||
|
||||
msgid "RAM saving is not available for FDS games!"
|
||||
msgstr "La sauvegarde RAM n'est pas disponible pour les jeux sur disquette (Famicom Disk System) !"
|
||||
|
||||
msgid "Reboot"
|
||||
msgstr "Redémarrer"
|
||||
|
||||
@ -289,6 +565,9 @@ msgstr "Réinitialiser"
|
||||
msgid "Reset Game"
|
||||
msgstr "Réinitialiser le Jeu"
|
||||
|
||||
msgid "Reset this game? Any unsaved progress will be lost."
|
||||
msgstr "Redémarrer ce jeu ? Toute progression non sauvegardée sera perdue."
|
||||
|
||||
msgid "Reset Mappings"
|
||||
msgstr "Réinit. les touches"
|
||||
|
||||
@ -310,6 +589,9 @@ msgstr "Droite"
|
||||
msgid "RIGHT"
|
||||
msgstr "DROITE"
|
||||
|
||||
msgid "Right Button"
|
||||
msgstr "Clic droit"
|
||||
|
||||
msgid "Rumble"
|
||||
msgstr "Vibration"
|
||||
|
||||
@ -319,17 +601,29 @@ msgstr "Sauver"
|
||||
msgid "Save Device"
|
||||
msgstr "Périph. de sauvegarde"
|
||||
|
||||
msgid "Save failed!"
|
||||
msgstr "La sauvegarde a échoué !"
|
||||
|
||||
msgid "Save file not found"
|
||||
msgstr "Pas de fichier de sauvegarde trouvé"
|
||||
|
||||
msgid "Save Folder"
|
||||
msgstr "Dossier des sauv."
|
||||
|
||||
msgid "Save Game"
|
||||
msgstr "Sauvegarder la partie"
|
||||
|
||||
msgid "Save RAM and State?"
|
||||
msgstr "Sauver la RAM et la position du jeu (sauvegarde d'état) ?"
|
||||
|
||||
msgid "Save Snapshot?"
|
||||
msgstr "Sauver la position du jeu ?"
|
||||
msgstr "Sauver la position du jeu (sauvegarde d'état) ?"
|
||||
|
||||
msgid "Save SRAM and Snapshot?"
|
||||
msgstr "Sauver la SRAM et la position du jeu ?"
|
||||
msgstr "Sauver la SRAM et la position du jeu (sauvegarde d'état) ?"
|
||||
|
||||
msgid "Save State?"
|
||||
msgstr "Sauver la position du jeu (sauvegarde d'état) ?"
|
||||
|
||||
msgid "Save successful"
|
||||
msgstr "Sauvegarde réussie"
|
||||
@ -337,6 +631,12 @@ msgstr "Sauvegarde réussie"
|
||||
msgid "Saving"
|
||||
msgstr "Sauvegarde"
|
||||
|
||||
msgid "Saving preferences..."
|
||||
msgstr "Sauvegarde des préférences en cours..."
|
||||
|
||||
msgid "Saving..."
|
||||
msgstr "Sauvegarde en cours..."
|
||||
|
||||
msgid "Scaling"
|
||||
msgstr "Format"
|
||||
|
||||
@ -346,6 +646,12 @@ msgstr "Position de l'écran"
|
||||
msgid "Screen Zoom"
|
||||
msgstr "Zoom écran"
|
||||
|
||||
msgid "Select"
|
||||
msgstr "Select"
|
||||
|
||||
msgid "Seek error!"
|
||||
msgstr "Erreur de positionnement ! (seek error)"
|
||||
|
||||
msgid "Settings"
|
||||
msgstr "Paramètres"
|
||||
|
||||
@ -356,25 +662,37 @@ msgid "Settings - Network"
|
||||
msgstr "Paramètres - Réseau"
|
||||
|
||||
msgid "Settings - Saving & Loading"
|
||||
msgstr "Paramètres - Sauv. & Chargement"
|
||||
msgstr "Paramètres - Sauvegarde & Chargement"
|
||||
|
||||
msgid "SD Card"
|
||||
msgstr "Carte SD"
|
||||
|
||||
msgid "SD card not found!"
|
||||
msgstr "Carte SD introuvable !"
|
||||
|
||||
msgid "Shift"
|
||||
msgstr "Maj"
|
||||
|
||||
msgid "Simp_chinese"
|
||||
msgstr "Chinois simplifié"
|
||||
|
||||
msgid "SMB Share IP"
|
||||
msgstr "IP Partage SMB"
|
||||
msgstr "IP partagée SMB"
|
||||
|
||||
msgid "SMB Share Name"
|
||||
msgstr "Nom Partage SMB"
|
||||
msgstr "Nom du Partage SMB"
|
||||
|
||||
msgid "SMB Share Password"
|
||||
msgstr "Mot de passe partage SMB"
|
||||
msgstr "Mot de passe de partage SMB"
|
||||
|
||||
msgid "SMB Share Username"
|
||||
msgstr "Utilisateur Partage SMB"
|
||||
msgstr "Nom d'utilisateur de partage SMB"
|
||||
|
||||
msgid "Snapshot"
|
||||
msgstr "Sauv. d'état"
|
||||
msgstr "Sauvegarde d'état"
|
||||
|
||||
msgid "Snapshot (Auto)"
|
||||
msgstr "Sauv. d'état (Auto)"
|
||||
|
||||
msgid "SNES Controller"
|
||||
msgstr "Manette SNES"
|
||||
@ -385,27 +703,93 @@ msgstr "Manettes SNES (2)"
|
||||
msgid "SNES Controllers (4)"
|
||||
msgstr "Manettes SNES (4)"
|
||||
|
||||
msgid "SNES Mouse"
|
||||
msgstr "Souris SNES"
|
||||
msgid "SNES Controller - Classic Controller"
|
||||
msgstr "Manette SNES - Manette Classique"
|
||||
|
||||
msgid "SNES Controller - GameCube Controller"
|
||||
msgstr "Manette SNES - Manette GameCube"
|
||||
|
||||
msgid "SNES Controller - Nunchuk + Wiimote"
|
||||
msgstr "Manette SNES - Nunchuk + Wiimote"
|
||||
|
||||
msgid "SNES Controller - Wiimote"
|
||||
msgstr "Manette SNES - Wiimote"
|
||||
|
||||
msgid "SNES Mouse"
|
||||
msgstr "Souris SNES"
|
||||
|
||||
msgid "SNES Mouse - GameCube Controller"
|
||||
msgstr "Souris SNES - Manette GameCube"
|
||||
|
||||
msgid "SNES Mouse - Wiimote"
|
||||
msgstr "Souris SNES - Wiimote"
|
||||
|
||||
msgid "Snes9x - Copyright (c) Snes9x Team 1996 - 2006"
|
||||
msgstr "Snes9x - Copyright (c) Snes9x Team 1996 - 2006"
|
||||
|
||||
msgid "Sound Effects Volume"
|
||||
msgstr "Volume des effets sonores"
|
||||
|
||||
msgid "Super Scope"
|
||||
msgid "Spanish"
|
||||
msgstr "Espagnol"
|
||||
|
||||
msgid "Sprite Limit"
|
||||
msgstr "Limite de Sprites"
|
||||
|
||||
msgid "SRAM file not found"
|
||||
msgstr "Pas de sauvegarde SRAM trouvée"
|
||||
|
||||
msgid "State"
|
||||
msgstr "Sauvegarde d'état"
|
||||
|
||||
msgid "State (Auto)"
|
||||
msgstr "Sauv. d'état (Auto)"
|
||||
|
||||
msgid "State file not found"
|
||||
msgstr "Pas de sauvegarde d'état trouvée"
|
||||
|
||||
msgid "Stretch to Fit"
|
||||
msgstr "Plein écran"
|
||||
|
||||
msgid "Superscope"
|
||||
msgstr "Super Scope"
|
||||
|
||||
msgid "Superscope - GameCube Controller"
|
||||
msgstr "Super Scope - Manette GameCube"
|
||||
|
||||
msgid "Superscope - Wiimote"
|
||||
msgstr "Super Scope - Wiimote"
|
||||
|
||||
msgid "This software is open source and may be copied,"
|
||||
msgstr "Cette application est libre et peut être copiée,"
|
||||
|
||||
msgid "Trad_chinese"
|
||||
msgstr "Chinois traditionnel"
|
||||
|
||||
msgid "Unable to initialize network!"
|
||||
msgstr "Impossible d'initialiser le réseau !"
|
||||
|
||||
msgid "Unable to locate a load device!"
|
||||
msgstr "Périphérique d'entrée introuvable !"
|
||||
|
||||
msgid "Unable to locate a save device!"
|
||||
msgstr "Périphérique de sauvegarde introuvable !"
|
||||
|
||||
msgid "Unable to open snapshot!"
|
||||
msgstr "Impossible d'ouvrir la sauvegarde d'état"
|
||||
|
||||
msgid "Unfiltered"
|
||||
msgstr "Non-filtré"
|
||||
|
||||
msgid "Unknown file type!"
|
||||
msgstr "Type de fichier inconnu !"
|
||||
|
||||
msgid "Unrecognized DVD format."
|
||||
msgstr "Format du DVD inconnu."
|
||||
|
||||
msgid "Unrecognized file extension!"
|
||||
msgstr "L'extension du fichier est inconnu !"
|
||||
|
||||
msgid "Up"
|
||||
msgstr "Haut"
|
||||
|
||||
@ -418,11 +802,23 @@ msgstr "Dossier Parent"
|
||||
msgid "Update Available"
|
||||
msgstr "Mise à jour disponible"
|
||||
|
||||
msgid "Update failed!"
|
||||
msgstr "La mise à jour a échouée !"
|
||||
|
||||
msgid "Update later"
|
||||
msgstr "Mise à jour Plus tard"
|
||||
msgstr "Mise à jour plus tard"
|
||||
|
||||
msgid "Update now"
|
||||
msgstr "Mise à jour Maintenant"
|
||||
msgstr "Mise à jour maintenant"
|
||||
|
||||
msgid "Update successful!"
|
||||
msgstr "La mise à jour a réussie !"
|
||||
|
||||
msgid "USB drive not found!"
|
||||
msgstr "Aucun disque USB n'a été trouvé !"
|
||||
|
||||
msgid "USB Mass Storage"
|
||||
msgstr "Périphérique de stockage USB"
|
||||
|
||||
msgid "Vertical"
|
||||
msgstr "Vertical"
|
||||
@ -433,6 +829,15 @@ msgstr "Vidéo"
|
||||
msgid "Video Mode"
|
||||
msgstr "Mode Vidéo"
|
||||
|
||||
msgid "VM8: Unknown page type!"
|
||||
msgstr "VM8 : Type de page inconnu !"
|
||||
|
||||
msgid "VM16: Unknown page type!"
|
||||
msgstr "VM16 : Type de page inconnu !"
|
||||
|
||||
msgid "VM32: Unknown page type!"
|
||||
msgstr "VM32 : Type de page inconnu !"
|
||||
|
||||
msgid "Wiimote"
|
||||
msgstr "Wiimote"
|
||||
|
||||
@ -441,4 +846,9 @@ msgstr "Orientation de la Wiimote"
|
||||
|
||||
msgid "Yes"
|
||||
msgstr "Oui"
|
||||
|
||||
|
||||
msgid "Zapper"
|
||||
msgstr "Nintendo Zapper"
|
||||
|
||||
msgid "Zapper Crosshair"
|
||||
msgstr "Réticule du Zapper"
|
@ -795,41 +795,41 @@ static void WindowCredits(void * ptr)
|
||||
FTGX_JUSTIFY_LEFT | FTGX_ALIGN_TOP, ALIGN_LEFT, ALIGN_TOP);
|
||||
|
||||
txt[i] = new GuiText("Coding & menu design");
|
||||
txt[i]->SetPosition(40,y); i++;
|
||||
txt[i]->SetPosition(60,y); i++;
|
||||
txt[i] = new GuiText("Tantric");
|
||||
txt[i]->SetPosition(335,y); i++; y+=24;
|
||||
txt[i]->SetPosition(350,y); i++; y+=24;
|
||||
txt[i] = new GuiText("Coding");
|
||||
txt[i]->SetPosition(40,y); i++;
|
||||
txt[i]->SetPosition(60,y); i++;
|
||||
txt[i] = new GuiText("michniewski");
|
||||
txt[i]->SetPosition(335,y); i++; y+=24;
|
||||
txt[i]->SetPosition(350,y); i++; y+=24;
|
||||
txt[i] = new GuiText("Menu artwork");
|
||||
txt[i]->SetPosition(40,y); i++;
|
||||
txt[i]->SetPosition(60,y); i++;
|
||||
txt[i] = new GuiText("the3seashells");
|
||||
txt[i]->SetPosition(335,y); i++; y+=24;
|
||||
txt[i]->SetPosition(350,y); i++; y+=24;
|
||||
txt[i] = new GuiText("Menu sound");
|
||||
txt[i]->SetPosition(40,y); i++;
|
||||
txt[i]->SetPosition(60,y); i++;
|
||||
txt[i] = new GuiText("Peter de Man");
|
||||
txt[i]->SetPosition(335,y); i++; y+=48;
|
||||
txt[i]->SetPosition(350,y); i++; y+=48;
|
||||
|
||||
txt[i] = new GuiText("Snes9x GX GameCube");
|
||||
txt[i]->SetPosition(40,y); i++;
|
||||
txt[i]->SetPosition(60,y); i++;
|
||||
txt[i] = new GuiText("SoftDev, crunchy2,");
|
||||
txt[i]->SetPosition(335,y); i++; y+=24;
|
||||
txt[i]->SetPosition(350,y); i++; y+=24;
|
||||
txt[i] = new GuiText("eke-eke, others");
|
||||
txt[i]->SetPosition(335,y); i++; y+=24;
|
||||
txt[i]->SetPosition(350,y); i++; y+=24;
|
||||
txt[i] = new GuiText("Snes9x");
|
||||
txt[i]->SetPosition(40,y); i++;
|
||||
txt[i]->SetPosition(60,y); i++;
|
||||
txt[i] = new GuiText("Snes9x Team");
|
||||
txt[i]->SetPosition(335,y); i++; y+=24;
|
||||
txt[i]->SetPosition(350,y); i++; y+=24;
|
||||
|
||||
txt[i] = new GuiText("libogc / devkitPPC");
|
||||
txt[i]->SetPosition(40,y); i++;
|
||||
txt[i]->SetPosition(60,y); i++;
|
||||
txt[i] = new GuiText("shagkur & wintermute");
|
||||
txt[i]->SetPosition(335,y); i++; y+=24;
|
||||
txt[i]->SetPosition(350,y); i++; y+=24;
|
||||
txt[i] = new GuiText("FreeTypeGX");
|
||||
txt[i]->SetPosition(40,y); i++;
|
||||
txt[i]->SetPosition(60,y); i++;
|
||||
txt[i] = new GuiText("Armin Tamzarian");
|
||||
txt[i]->SetPosition(335,y); i++; y+=48;
|
||||
txt[i]->SetPosition(350,y); i++; y+=48;
|
||||
|
||||
txt[i]->SetPresets(18, (GXColor){0, 0, 0, 255}, 0,
|
||||
FTGX_JUSTIFY_CENTER | FTGX_ALIGN_TOP, ALIGN_CENTRE, ALIGN_TOP);
|
||||
@ -3724,7 +3724,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