OcttBitsOfFun/LumaBmp2NinJpg/source/main.c

517 lines
14 KiB
C
Raw Normal View History

2024-02-11 18:52:02 +01:00
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <dirent.h>
#include <inttypes.h>
//#include "cjpeg.h"
//#include "cio.h"
#ifdef __3DS__
#include <3ds.h>
#endif
#define PathStringSize 128
#ifdef __3DS__
#define ScreenshotsPath "sdmc:/luma/screenshots/"
#define ScreenshotsBakPath "sdmc:/luma/screenshots-old/"
#define DcimPath "sdmc:/DCIM/"
#define mkdir(path) { mkdir(path, 7777); }
#define DirListPrepare(dir) {}
#else
#define ScreenshotsPath "./luma/screenshots/"
#define ScreenshotsBakPath "./luma/screenshots-old/"
#define DcimPath "./DCIM/"
#define DirListPrepare(dir) { readdir(dir); readdir(dir); } // exclude `.` and `..` from list
#endif
#define IsStringEqual(s1, s2) ( strcmp(s1, s2) == 0 )
#define IsStringEmpty(str) ( IsStringEqual(str, "") )
#define ExistDirectory(path) ( opendir(path) != NULL )
#define MkDirIfNotExist(path) { if (!ExistDirectory(path)) mkdir(path); }
#define Try(flag, then) { if (!(flag)) { then; printf("A fatal error occured.\n"); Exit(); } }
void Exit (void)
{
printf("The program will now exit.\n");
#ifdef __3DS__
sleep(3);
gfxExit();
#endif
exit(0);
}
char *GetLastDirectoryItem (const char path[], char *buffer)
{
DIR *directory;
struct dirent *dirEntry;
memset(buffer, 0, PathStringSize);
if ((directory = opendir(path)) != NULL) {
DirListPrepare(directory);
while ((dirEntry = readdir(directory)) != NULL) {
strcpy(buffer, dirEntry->d_name);
}
closedir(directory);
} else {
printf("Error reading `%s` directory.\n", path);
Exit();
}
return buffer;
}
bool IsDirectoryEmpty (char *path) {
char buffer[PathStringSize];
return IsStringEmpty(GetLastDirectoryItem(path, buffer));
}
char *GetDcimNinNameFromIndex (int index, char *buffer)
{
char indexString[5];
sprintf(buffer, "%dNIN03/", index);
return buffer;
}
char *GetDcimNinFullPathFromIndex (int index, char *buffer)
{
char name[PathStringSize];
return strcat( strcpy(buffer, DcimPath), GetDcimNinNameFromIndex(index, name) );
}
void *MakeDcimNinFolderFromIndex (int index)
{
char path[PathStringSize];
mkdir(GetDcimNinFullPathFromIndex(index, path));
}
int GetDcimNinIndexFromPath (char *path)
{
char indexStr[4];
indexStr[0] = path[0];
indexStr[1] = path[1];
indexStr[2] = path[2];
return atoi(indexStr);
}
int GetHniXIndexFromPath (char *path)
{
char indexStr[5];
int pathExtIndex = (strlen(path) - 1 - 4);
indexStr[0] = path[pathExtIndex - 3];
indexStr[1] = path[pathExtIndex - 2];
indexStr[2] = path[pathExtIndex - 1];
indexStr[3] = path[pathExtIndex - 0];
//printf(". %s %s\n", path, indexStr);
return atoi(indexStr);
}
bool IsXNinFolderFullFromIndex (int index)
{
char path[PathStringSize], buffer[PathStringSize];
char *curXNinFullPath = GetDcimNinFullPathFromIndex(index, path);
char *lastHniXPath = GetLastDirectoryItem(curXNinFullPath, buffer);
int lastHniXIndex = GetHniXIndexFromPath(lastHniXPath);
//printf("%s %s %d", curXNinFullPath, lastHniXPath, lastHniXIndex);
return ( lastHniXIndex >= 100 );
}
//bool ConvertImage (char *bmpPath, char *jpgPath) {
/* FILE *bmpFile, *jpgFile;
bmp_info bmpInfo;
compress_io compressIo;
if ( (bmpFile = fopen(bmpPath, "rb")) == NULL || !is_bmp(bmpFile) ) {
return false;
}
if ( (jpgFile = fopen(jpgPath, "wb")) == NULL ) {
return false;
}
read_bmp(bmpFile, &bmpInfo);
init_mem(&compressIo, bmpFile, ((bmpInfo.width * 3 + 3) / 4 * 4 * DCTSIZE), jpgFile, MEM_OUT_SIZE);
jpeg_encode(&compressIo, &bmpInfo);
if ( !(compressIo.out->flush_buffer)(&compressIo) ) {
return false;
}
free_mem(&compressIo);
fclose(bmpFile);
fclose(jpgFile);
return true;
*/
//}
char *ReadFilepathIntoBuffer (char filepath[], size_t *sizeOut) {
//size_t ReadFilepathIntoBuffer (char filepath[], char *buffer) {
size_t size;
char *buffer;
FILE *file;
Try((file = fopen(filepath, "rb")), {});
fseek(file, 0L, SEEK_END);
size = ftell(file);
rewind(file);
Try((buffer = calloc(1, size+1)), { fclose(file); })
if ( fread(buffer, size, 1, file) != 1 ) {
fclose(file);
free(buffer);
Exit();
}
fclose(file);
*sizeOut = size;
return buffer;//size;
}
void WriteBufferIntoFilepath(char *buffer, size_t size, char filepath[]) {
FILE *file;
Try((file= fopen(filepath, "wb")), {});
fwrite(buffer, size, 1, file);
fclose(file);
}
#ifdef __3DS__
u8 *HttpPostBmpForJpg(const char* url, const char* data, size_t len, /*char *outBuffer*/size_t *outSize) {
Result ret=0;
httpcContext context;
u32 statuscode=0;
u32 contentsize=0, readsize=0, size=0;
u8 *buf, *lastbuf;
httpcOpenContext(&context, HTTPC_METHOD_POST, url, 0);
httpcSetSSLOpt(&context, SSLCOPT_DisableVerify);
httpcSetKeepAlive(&context, HTTPC_KEEPALIVE_ENABLED);
httpcAddRequestHeaderField(&context, "User-Agent", "LumaBmp2NinJpg/1.0.0");
httpcAddRequestHeaderField(&context, "Content-Type", "image/bmp");
httpcAddPostDataRaw(&context, (u32*)data, len);
//printf("1\n");
//sleep(1);
ret = httpcBeginRequest(&context);
if(ret!=0){
httpcCloseContext(&context);
return ret;
}
//printf("2\n");
//sleep(1);
ret = httpcGetResponseStatusCode(&context, &statuscode);
//printf("r %d %d\n",ret,statuscode);
//sleep(1);
if(ret!=0){
httpcCloseContext(&context);
return ret;
}
//printf("3\n");
//sleep(1);
if(statuscode!=200){
httpcCloseContext(&context);
return -2;
}
//printf("4\n");
//sleep(1);
ret=httpcGetDownloadSizeState(&context, NULL, &contentsize);
if(ret!=0){
httpcCloseContext(&context);
return ret;
}
//printf("5\n");
//sleep(1);
buf = (u8*)malloc(0x1000);
if(buf==NULL){
httpcCloseContext(&context);
return -1;
}
//printf("6\n");
//sleep(1);
do {
// This download loop resizes the buffer as data is read.
ret = httpcDownloadData(&context, buf+size, 0x1000, &readsize);
size += readsize;
if (ret == (s32)HTTPC_RESULTCODE_DOWNLOADPENDING){
lastbuf = buf; // Save the old pointer, in case realloc() fails.
buf = realloc(buf, size + 0x1000);
if(buf==NULL){
httpcCloseContext(&context);
free(lastbuf);
return -1;
}
}
} while (ret == (s32)HTTPC_RESULTCODE_DOWNLOADPENDING);
//printf("7\n");
//sleep(1);
if(ret!=0){
httpcCloseContext(&context);
free(buf);
return -1;
}
//printf("8\n");
//sleep(1);
// Resize the buffer back down to our actual final size
lastbuf = buf;
buf = realloc(buf, size);
if(buf==NULL){ // realloc() failed.
httpcCloseContext(&context);
free(lastbuf);
return -1;
}
//printf("9\n");
//sleep(1);
httpcCloseContext(&context);
*outSize = size;
return buf;//size;
/*
Result ret=0;
httpcContext context;
char *newurl=NULL;
u32 statuscode=0;
u32 contentsize=0, readsize=0, size=0;
u8 *buf, *lastbuf;
printf("POSTing %s\n", url);
do {
ret = httpcOpenContext(&context, HTTPC_METHOD_POST, url, 0);
printf("return from httpcOpenContext: %" PRIx32 "\n",ret);
// This disables SSL cert verification, so https:// will be usable
ret = httpcSetSSLOpt(&context, SSLCOPT_DisableVerify);
printf("return from httpcSetSSLOpt: %" PRIx32 "\n",ret);
// Enable Keep-Alive connections
ret = httpcSetKeepAlive(&context, HTTPC_KEEPALIVE_ENABLED);
printf("return from httpcSetKeepAlive: %" PRIx32 "\n",ret);
// Set a User-Agent header so websites can identify your application
ret = httpcAddRequestHeaderField(&context, "User-Agent", "LumaBmp2NinJpg/1.0.0");
printf("return from httpcAddRequestHeaderField: %" PRIx32 "\n",ret);
// Set a Content-Type header so websites can identify the format of our raw body data.
// If you want to send form data in your request, use:
//ret = httpcAddRequestHeaderField(&context, "Content-Type", "multipart/form-data");
// If you want to send raw JSON data in your request, use:
ret = httpcAddRequestHeaderField(&context, "Content-Type", "image/bmp");//"application/json");
printf("return from httpcAddRequestHeaderField: %" PRIx32 "\n",ret);
// Post specified data.
// If you want to add a form field to your request, use:
//ret = httpcAddPostDataAscii(&context, "data", value);
// If you want to add a form field containing binary data to your request, use:
//ret = httpcAddPostDataBinary(&context, "field name", yourBinaryData, length);
// If you want to add raw data to your request, use:
ret = httpcAddPostDataRaw(&context, (u32*)data, len);
printf("return from httpcAddPostDataRaw: %" PRIx32 "\n",ret);
ret = httpcBeginRequest(&context);
if(ret!=0){
httpcCloseContext(&context);
if(newurl!=NULL) free(newurl);
return ret;
}
ret = httpcGetResponseStatusCode(&context, &statuscode);
if(ret!=0){
httpcCloseContext(&context);
if(newurl!=NULL) free(newurl);
return ret;
}
if ((statuscode >= 301 && statuscode <= 303) || (statuscode >= 307 && statuscode <= 308)) {
if(newurl==NULL) newurl = malloc(0x1000); // One 4K page for new URL
if (newurl==NULL){
httpcCloseContext(&context);
return -1;
}
ret = httpcGetResponseHeader(&context, "Location", newurl, 0x1000);
url = newurl; // Change pointer to the url that we just learned
printf("redirecting to url: %s\n",url);
httpcCloseContext(&context); // Close this context before we try the next
}
} while ((statuscode >= 301 && statuscode <= 303) || (statuscode >= 307 && statuscode <= 308));
if(statuscode!=200){
printf("URL returned status: %" PRIx32 "\n", statuscode);
httpcCloseContext(&context);
if(newurl!=NULL) free(newurl);
return -2;
}
// This relies on an optional Content-Length header and may be 0
ret=httpcGetDownloadSizeState(&context, NULL, &contentsize);
if(ret!=0){
httpcCloseContext(&context);
if(newurl!=NULL) free(newurl);
return ret;
}
printf("reported size: %" PRIx32 "\n",contentsize);
// Start with a single page buffer
buf = (u8*)malloc(0x1000);
if(buf==NULL){
httpcCloseContext(&context);
if(newurl!=NULL) free(newurl);
return -1;
}
do {
// This download loop resizes the buffer as data is read.
ret = httpcDownloadData(&context, buf+size, 0x1000, &readsize);
size += readsize;
if (ret == (s32)HTTPC_RESULTCODE_DOWNLOADPENDING){
lastbuf = buf; // Save the old pointer, in case realloc() fails.
buf = realloc(buf, size + 0x1000);
if(buf==NULL){
httpcCloseContext(&context);
free(lastbuf);
if(newurl!=NULL) free(newurl);
return -1;
}
}
} while (ret == (s32)HTTPC_RESULTCODE_DOWNLOADPENDING);
if(ret!=0){
httpcCloseContext(&context);
if(newurl!=NULL) free(newurl);
free(buf);
return -1;
}
// Resize the buffer back down to our actual final size
lastbuf = buf;
buf = realloc(buf, size);
if(buf==NULL){ // realloc() failed.
httpcCloseContext(&context);
free(lastbuf);
if(newurl!=NULL) free(newurl);
return -1;
}
printf("response size: %" PRIx32 "\n",size);
printf("%s\n",buf);
gfxFlushBuffers();
gfxSwapBuffers();
httpcCloseContext(&context);
//free(buf);
if (newurl!=NULL) free(newurl);
*outSize = size;
return buf;//size;
*/
}
#endif
int main (int argc, char** argv)
{
int dcimFolderIndex = 100;
char initDcimNinPath[PathStringSize];
#ifdef __3DS__
PrintConsole bottomScreen;
gfxInitDefault();
consoleInit(GFX_BOTTOM, &bottomScreen);
consoleSelect(&bottomScreen);
httpcInit(4 * 1024 * 1024);
#endif
//size_t len1;
//char *buf1 = HttpPostBmpForJpg("https://httpbin.org/post", "{\"foo\": \"bar\"}", 19, &len1);
//printf("%d %s\n",len1,buf1);
//sleep(1);
if (!ExistDirectory(ScreenshotsPath)) {
printf("The `%s` directory doesn't exist. Nothing to do.\n", ScreenshotsPath);
Exit();
}
if (IsDirectoryEmpty(ScreenshotsPath)) {
printf("No files present in `%s`. Nothing to do.\n", ScreenshotsPath);
Exit();
}
MkDirIfNotExist(ScreenshotsBakPath);
MkDirIfNotExist(DcimPath);
if (IsDirectoryEmpty(DcimPath)) {
MakeDcimNinFolderFromIndex(dcimFolderIndex);
}
GetLastDirectoryItem(DcimPath, initDcimNinPath);
dcimFolderIndex = GetDcimNinIndexFromPath(initDcimNinPath);
struct dirent *dirEntry;
DIR *directory = opendir(ScreenshotsPath);
DirListPrepare(directory);
while ((dirEntry = readdir(directory)) != NULL) {
char srcPath[PathStringSize], srcPathBak[PathStringSize], dstName[PathStringSize], dstPath[PathStringSize];
char currDcimNinName[PathStringSize], currDcimNinPath[PathStringSize], lastJpgName[PathStringSize];
if (IsXNinFolderFullFromIndex(dcimFolderIndex)) {
MakeDcimNinFolderFromIndex(++dcimFolderIndex);
}
GetLastDirectoryItem(DcimPath, currDcimNinName);
sprintf(currDcimNinPath, "%s%s/", DcimPath, currDcimNinName);
GetLastDirectoryItem(currDcimNinPath, lastJpgName);
int currJpgIndex = (GetHniXIndexFromPath(lastJpgName) + 1);
sprintf(srcPath, "%s%s", ScreenshotsPath, dirEntry->d_name);
sprintf(srcPathBak, "%s%s", ScreenshotsBakPath, dirEntry->d_name);
sprintf(dstName, "%dNIN03/HNI_%04d.JPG", dcimFolderIndex, currJpgIndex);
sprintf(dstPath, "%s%s", DcimPath, dstName);
printf("* %s => %s ...", dirEntry->d_name, dstName);
#ifdef __3DS__
char *bmpData, *jpgData;
size_t bmpSize, jpgSize;
//size_t bmpSize = ReadFilepathIntoBuffer(srcPath, bmpData);
bmpData = ReadFilepathIntoBuffer(srcPath, &bmpSize);
//printf("%d %s\n", bmpSize, bmpData);
//sleep(3);
//size_t jpgSize = HttpPostBmpForJpg("https://hlb0.octt.eu.org/LumaBmp2NinJpgConvert.php", bmpData, bmpSize, jpgData);
jpgData = HttpPostBmpForJpg("http://hlb0.octt.eu.org/LumaBmp2NinJpgConvert.php", bmpData, bmpSize, &jpgSize);
//sleep(5);
//printf("%d %s\n", jpgSize, jpgData);
//sleep(3);
free(bmpData);
if (jpgSize > 0) {
printf("Done!\n");
WriteBufferIntoFilepath(jpgData, jpgSize, dstPath);
#endif
rename(srcPath, srcPathBak);
//rename(srcPath, dstPath);
#ifndef __3DS__
printf("\n");
#endif
#ifdef __3DS__
} else {
printf("Fail!\n");
}
free(jpgData);
#endif
}
closedir(directory);
Exit();
}