From 53cd218d95630f518d6dc41fc2694d5a12aa1d30 Mon Sep 17 00:00:00 2001 From: OctoSpacc Date: Sun, 11 Feb 2024 18:52:02 +0100 Subject: [PATCH] LumaBmp2NinJpg --- LumaBmp2NinJpg/.gitignore | 3 + LumaBmp2NinJpg/LumaBmp2NinJpg.3dsx | Bin 0 -> 182764 bytes LumaBmp2NinJpg/LumaBmp2NinJpg.smdh | Bin 0 -> 14016 bytes LumaBmp2NinJpg/Makefile | 229 +++++++++++++ LumaBmp2NinJpg/source/cio.c | 175 ++++++++++ LumaBmp2NinJpg/source/cio.h | 36 ++ LumaBmp2NinJpg/source/cjpeg.c | 384 +++++++++++++++++++++ LumaBmp2NinJpg/source/cjpeg.h | 310 +++++++++++++++++ LumaBmp2NinJpg/source/cmarker.c | 232 +++++++++++++ LumaBmp2NinJpg/source/fdctflt.c | 124 +++++++ LumaBmp2NinJpg/source/main.c | 516 +++++++++++++++++++++++++++++ LumaBmp2NinJpg/source/rdbmp.c | 50 +++ 12 files changed, 2059 insertions(+) create mode 100644 LumaBmp2NinJpg/.gitignore create mode 100644 LumaBmp2NinJpg/LumaBmp2NinJpg.3dsx create mode 100644 LumaBmp2NinJpg/LumaBmp2NinJpg.smdh create mode 100644 LumaBmp2NinJpg/Makefile create mode 100644 LumaBmp2NinJpg/source/cio.c create mode 100644 LumaBmp2NinJpg/source/cio.h create mode 100644 LumaBmp2NinJpg/source/cjpeg.c create mode 100644 LumaBmp2NinJpg/source/cjpeg.h create mode 100644 LumaBmp2NinJpg/source/cmarker.c create mode 100644 LumaBmp2NinJpg/source/fdctflt.c create mode 100644 LumaBmp2NinJpg/source/main.c create mode 100644 LumaBmp2NinJpg/source/rdbmp.c diff --git a/LumaBmp2NinJpg/.gitignore b/LumaBmp2NinJpg/.gitignore new file mode 100644 index 0000000..3c4bb72 --- /dev/null +++ b/LumaBmp2NinJpg/.gitignore @@ -0,0 +1,3 @@ +/build +*.elf +*.exe diff --git a/LumaBmp2NinJpg/LumaBmp2NinJpg.3dsx b/LumaBmp2NinJpg/LumaBmp2NinJpg.3dsx new file mode 100644 index 0000000000000000000000000000000000000000..c77d0680d0a24c05659740951a5cbdf63ba3b4dc GIT binary patch literal 182764 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

SS#Z;x8@+%KIa;p3`K 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 BeO&+m literal 0 HcmV?d00001 diff --git a/LumaBmp2NinJpg/LumaBmp2NinJpg.smdh b/LumaBmp2NinJpg/LumaBmp2NinJpg.smdh new file mode 100644 index 0000000000000000000000000000000000000000..0fc6351c29effec071a7825715a971f4e0982343 GIT binary patch literal 14016 zcmeHMPe@!x7@uBb4<35(uwcPgSV|6ih$ROP0a>X~rS_0ENQDSnyKR?f+qAJIh!+Wa z2qg!T%_$TS^dPB14!POO;_kCTvJVfE4S3l@59{Jd_pp%H?|b9V8K-am)IVuyXU4a` zZ@%xF-+S}Tym>R@CnFzxC@6g-rp1&S?_ zk)ZZ*EWV|dUSzWUf05B`&29VNzW?_9xAVW9|LynRe*f+I&#wRM`roeq?f%d1|Lp$X z?*Dl`V9$SApCX*z!=C?~K6d9()1Lp>^B;TuW6yu=`HwySvFAVb{KuaE*z=z^dH%Do zAcDUI`sL(P3WTGd#9Mkv$z4n7;q)$F3##t%p3&~{ z{tlFNoGnORpl)LsdPaZEU+Wp|8D-?$-+?S;=yjCdT&vOj?>sl}IrnyLU5Ikj)XP@Y zpF!W>!L8~ZN4XhZ|25p2>CN=A1;{e9-ugKk*Y#|le=`3>xWWap%-L~Q%d2JIhaULH zOX2$dvM0S_9!D!1&&Gi!KlDJ;4qhPhema?*WXuvm4}>1bvC77`yO|dW?FO>`@?BU} zT$;6CxP#QjM^)Sx$oJhZ^Y6(VDbf4lW{%>*wp?+p_<|z1Rk~N=@?ue5!kr50t1?>$ zz2B&Q%9|s(wvnJ;nXgnUrIq9Q&?@A(o;9buOwf-RLd7g4=4L(6v@aH&pk;lBxnjY4 zx~E#jBZXtNbC4^_7I68#5j*xjT`p`EHurPUJm>wH?Z=S;hq`$Cu_Gb_s;`p~C5K6^ z>|u4@jLr$Y&E>oG-DsX>jotb#&q<+9XHbF{Xi`BBH0@_CgBNJ>K@T+TXDx%bzB~WW zU*kEu-Q_nqRpV%`2z*he9j|^R&`6lM*dPaNl!2}N6Ck$P`*0XdCANk&ZXLgCs2N7WM!mU#TPs> zs(NJGtKW+MJnYGcb4=5<^kU}D^XUdFpJTT(3Gs>e1QP&FGU$P(T`$WhswnT!*v<4- z##mDstBmQskiiRt9tb_7VpbCKf?sKsq}#!%qt37EA?tR&&L38%m0hpXm+xAdx;aEUr1n!Qe%;QipUwxJ4}j)c3VNVv zZ?DYjQOA9{cZ1fbUDc#J%iF^sffs1!3#9~p$D3FvkYEfWBW?*oZtnT{?G$WyIFRqKX~U8mK|5_ zWY`v`olTndJm3YI^`Hlub}s9?j#+=sef3)Hf5QC#jxOO|r7_FC$W?2VMaGlEejoG-FDo>DPu7<`q}NA3ZUy^$y{DulNjqGg z4?jEP6M*Sz%!`+=`bl@Xim?KQaIC*h2K(o5>*=(P_V)6#IqoHTHs8Njnx%I^W*)!7 zT`9#jg}a)Amd_p{zen@64c6SxEow~4N0*ql?=W53q48g!am>+;guVf0q@9-B`h6P7 z=BVGId7FKC{$w=m&;uLswyST&-`Ktt8l`sc3%`qrD%k%`Sf<{b3Px&~u&`O%sBJ{^ Fe*$MaFsJ|k literal 0 HcmV?d00001 diff --git a/LumaBmp2NinJpg/Makefile b/LumaBmp2NinJpg/Makefile new file mode 100644 index 0000000..632882b --- /dev/null +++ b/LumaBmp2NinJpg/Makefile @@ -0,0 +1,229 @@ +#--------------------------------------------------------------------------------- +.SUFFIXES: +#--------------------------------------------------------------------------------- + +ifeq ($(strip $(DEVKITARM)),) +$(error "Please set DEVKITARM in your environment. export DEVKITARM=devkitARM") +endif + +TOPDIR ?= $(CURDIR) +include $(DEVKITARM)/3ds_rules + +#--------------------------------------------------------------------------------- +# TARGET is the name of the output +# BUILD is the directory where object files & intermediate files will be placed +# SOURCES is a list of directories containing source code +# DATA is a list of directories containing data files +# INCLUDES is a list of directories containing header files +# GRAPHICS is a list of directories containing graphics files +# GFXBUILD is the directory where converted graphics files will be placed +# If set to $(BUILD), it will statically link in the converted +# files as if they were data files. +# +# NO_SMDH: if set to anything, no SMDH file is generated. +# ROMFS is the directory which contains the RomFS, relative to the Makefile (Optional) +# APP_TITLE is the name of the app stored in the SMDH file (Optional) +# APP_DESCRIPTION is the description of the app stored in the SMDH file (Optional) +# APP_AUTHOR is the author of the app stored in the SMDH file (Optional) +# ICON is the filename of the icon (.png), relative to the project folder. +# If not set, it attempts to use one of the following (in this order): +# - .png +# - icon.png +# - /default_icon.png +#--------------------------------------------------------------------------------- +TARGET := $(notdir $(CURDIR)) +BUILD := build +SOURCES := source +DATA := data +INCLUDES := include +GRAPHICS := gfx +GFXBUILD := $(BUILD) +#ROMFS := romfs +#GFXBUILD := $(ROMFS)/gfx + +#--------------------------------------------------------------------------------- +# options for code generation +#--------------------------------------------------------------------------------- +ARCH := -march=armv6k -mtune=mpcore -mfloat-abi=hard -mtp=soft + +CFLAGS := -g -Wall -O2 -mword-relocations \ + -ffunction-sections \ + $(ARCH) + +CFLAGS += $(INCLUDE) -D__3DS__ + +CXXFLAGS := $(CFLAGS) -fno-rtti -fno-exceptions -std=gnu++11 + +ASFLAGS := -g $(ARCH) +LDFLAGS = -specs=3dsx.specs -g $(ARCH) -Wl,-Map,$(notdir $*.map) + +LIBS := -lctru -lm + +#--------------------------------------------------------------------------------- +# list of directories containing libraries, this must be the top level containing +# include and lib +#--------------------------------------------------------------------------------- +LIBDIRS := $(CTRULIB) + + +#--------------------------------------------------------------------------------- +# no real need to edit anything past this point unless you need to add additional +# rules for different file extensions +#--------------------------------------------------------------------------------- +ifneq ($(BUILD),$(notdir $(CURDIR))) +#--------------------------------------------------------------------------------- + +export OUTPUT := $(CURDIR)/$(TARGET) +export TOPDIR := $(CURDIR) + +export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \ + $(foreach dir,$(GRAPHICS),$(CURDIR)/$(dir)) \ + $(foreach dir,$(DATA),$(CURDIR)/$(dir)) + +export DEPSDIR := $(CURDIR)/$(BUILD) + +CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c))) +CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp))) +SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s))) +PICAFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.v.pica))) +SHLISTFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.shlist))) +GFXFILES := $(foreach dir,$(GRAPHICS),$(notdir $(wildcard $(dir)/*.t3s))) +BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*))) + +#--------------------------------------------------------------------------------- +# use CXX for linking C++ projects, CC for standard C +#--------------------------------------------------------------------------------- +ifeq ($(strip $(CPPFILES)),) +#--------------------------------------------------------------------------------- + export LD := $(CC) +#--------------------------------------------------------------------------------- +else +#--------------------------------------------------------------------------------- + export LD := $(CXX) +#--------------------------------------------------------------------------------- +endif +#--------------------------------------------------------------------------------- + +#--------------------------------------------------------------------------------- +ifeq ($(GFXBUILD),$(BUILD)) +#--------------------------------------------------------------------------------- +export T3XFILES := $(GFXFILES:.t3s=.t3x) +#--------------------------------------------------------------------------------- +else +#--------------------------------------------------------------------------------- +export ROMFS_T3XFILES := $(patsubst %.t3s, $(GFXBUILD)/%.t3x, $(GFXFILES)) +export T3XHFILES := $(patsubst %.t3s, $(BUILD)/%.h, $(GFXFILES)) +#--------------------------------------------------------------------------------- +endif +#--------------------------------------------------------------------------------- + +export OFILES_SOURCES := $(CPPFILES:.cpp=.o) $(CFILES:.c=.o) $(SFILES:.s=.o) + +export OFILES_BIN := $(addsuffix .o,$(BINFILES)) \ + $(PICAFILES:.v.pica=.shbin.o) $(SHLISTFILES:.shlist=.shbin.o) \ + $(addsuffix .o,$(T3XFILES)) + +export OFILES := $(OFILES_BIN) $(OFILES_SOURCES) + +export HFILES := $(PICAFILES:.v.pica=_shbin.h) $(SHLISTFILES:.shlist=_shbin.h) \ + $(addsuffix .h,$(subst .,_,$(BINFILES))) \ + $(GFXFILES:.t3s=.h) + +export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \ + $(foreach dir,$(LIBDIRS),-I$(dir)/include) \ + -I$(CURDIR)/$(BUILD) + +export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib) + +export _3DSXDEPS := $(if $(NO_SMDH),,$(OUTPUT).smdh) + +ifeq ($(strip $(ICON)),) + icons := $(wildcard *.png) + ifneq (,$(findstring $(TARGET).png,$(icons))) + export APP_ICON := $(TOPDIR)/$(TARGET).png + else + ifneq (,$(findstring icon.png,$(icons))) + export APP_ICON := $(TOPDIR)/icon.png + endif + endif +else + export APP_ICON := $(TOPDIR)/$(ICON) +endif + +ifeq ($(strip $(NO_SMDH)),) + export _3DSXFLAGS += --smdh=$(CURDIR)/$(TARGET).smdh +endif + +ifneq ($(ROMFS),) + export _3DSXFLAGS += --romfs=$(CURDIR)/$(ROMFS) +endif + +.PHONY: all clean + +#--------------------------------------------------------------------------------- +all: $(BUILD) $(GFXBUILD) $(DEPSDIR) $(ROMFS_T3XFILES) $(T3XHFILES) + @$(MAKE) --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile + +$(BUILD): + @mkdir -p $@ + +ifneq ($(GFXBUILD),$(BUILD)) +$(GFXBUILD): + @mkdir -p $@ +endif + +ifneq ($(DEPSDIR),$(BUILD)) +$(DEPSDIR): + @mkdir -p $@ +endif + +#--------------------------------------------------------------------------------- +clean: + @echo clean ... + @rm -fr $(BUILD) $(TARGET).3dsx $(OUTPUT).smdh $(TARGET).elf $(GFXBUILD) + +#--------------------------------------------------------------------------------- +$(GFXBUILD)/%.t3x $(BUILD)/%.h : %.t3s +#--------------------------------------------------------------------------------- + @echo $(notdir $<) + @tex3ds -i $< -H $(BUILD)/$*.h -d $(DEPSDIR)/$*.d -o $(GFXBUILD)/$*.t3x + +#--------------------------------------------------------------------------------- +else + +#--------------------------------------------------------------------------------- +# main targets +#--------------------------------------------------------------------------------- +$(OUTPUT).3dsx : $(OUTPUT).elf $(_3DSXDEPS) + +$(OFILES_SOURCES) : $(HFILES) + +$(OUTPUT).elf : $(OFILES) + +#--------------------------------------------------------------------------------- +# you need a rule like this for each extension you use as binary data +#--------------------------------------------------------------------------------- +%.bin.o %_bin.h : %.bin +#--------------------------------------------------------------------------------- + @echo $(notdir $<) + @$(bin2o) + +#--------------------------------------------------------------------------------- +.PRECIOUS : %.t3x %.shbin +#--------------------------------------------------------------------------------- +%.t3x.o %_t3x.h : %.t3x +#--------------------------------------------------------------------------------- + $(SILENTMSG) $(notdir $<) + $(bin2o) + +#--------------------------------------------------------------------------------- +%.shbin.o %_shbin.h : %.shbin +#--------------------------------------------------------------------------------- + $(SILENTMSG) $(notdir $<) + $(bin2o) + +-include $(DEPSDIR)/*.d + +#--------------------------------------------------------------------------------------- +endif +#--------------------------------------------------------------------------------------- diff --git a/LumaBmp2NinJpg/source/cio.c b/LumaBmp2NinJpg/source/cio.c new file mode 100644 index 0000000..b5fb939 --- /dev/null +++ b/LumaBmp2NinJpg/source/cio.c @@ -0,0 +1,175 @@ +/* Copyright (C) 2009 + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + * 02111-1307, USA. + * + */ + + + +#include +#include "cjpeg.h" +#include "cio.h" + + +/* + * flush input and output of compress IO. + */ + +bool +flush_cin_buffer(void *cio) +{ + mem_mgr *in = ((compress_io *) cio)->in; + size_t len = in->end - in->set; + memset(in->set, 0, len); + if (fread(in->set, sizeof(UINT8), len, in->fp) != len) + return false; +#ifdef REVERSED + fseek(in->fp, -len * 2, SEEK_CUR); +#endif + in->pos = in->set; + return true; +} + +bool +flush_cout_buffer(void *cio) +{ + mem_mgr *out = ((compress_io *) cio)->out; + size_t len = out->pos - out->set; + if (fwrite(out->set, sizeof(UINT8), len, out->fp) != len) + return false; + memset(out->set, 0, len); + out->pos = out->set; + return true; +} + + +/* + * init memory manager. + */ + +void +init_mem(compress_io *cio, + FILE *in_fp, int in_size, FILE *out_fp, int out_size) +{ + cio->in = (mem_mgr *) malloc(sizeof(mem_mgr)); + if (!cio->in) + err_exit(BUFFER_ALLOC_ERR); + cio->in->set = (UINT8 *) malloc(sizeof(UINT8) * in_size); + if (!cio->in->set) + err_exit(BUFFER_ALLOC_ERR); + cio->in->pos = cio->in->set; + cio->in->end = cio->in->set + in_size; + cio->in->flush_buffer = flush_cin_buffer; + cio->in->fp = in_fp; + + cio->out = (mem_mgr *) malloc(sizeof(mem_mgr)); + if (!cio->out) + err_exit(BUFFER_ALLOC_ERR); + cio->out->set = (UINT8 *) malloc(sizeof(UINT8) * out_size); + if (!cio->out->set) + err_exit(BUFFER_ALLOC_ERR); + cio->out->pos = cio->out->set; + cio->out->end = cio->out->set + out_size; + cio->out->flush_buffer = flush_cout_buffer; + cio->out->fp = out_fp; + + cio->temp_bits.len = 0; + cio->temp_bits.val = 0; +} + +void +free_mem(compress_io *cio) +{ + fflush(cio->out->fp); + free(cio->in->set); + free(cio->out->set); + free(cio->in); + free(cio->out); +} + + +/* + * write operations. + */ + +void +write_byte(compress_io *cio, UINT8 val) +{ + mem_mgr *out = cio->out; + *(out->pos)++ = val & 0xFF; + if (out->pos == out->end) { + if (!(out->flush_buffer)(cio)) + err_exit(BUFFER_WRITE_ERR); + } +} + +void +write_word(compress_io *cio, UINT16 val) +{ + write_byte(cio, (val >> 8) & 0xFF); + write_byte(cio, val & 0xFF); +} + +void +write_marker(compress_io *cio, JPEG_MARKER mark) +{ + write_byte(cio, 0xFF); + write_byte(cio, (int) mark); +} + +void +write_bits(compress_io *cio, BITS bits) +{ + BITS *temp = &(cio->temp_bits); + UINT16 word; + UINT8 byte1, byte2; + int len = bits.len + temp->len - 16; + if (len >= 0) { + word = temp->val | bits.val >> len; + byte1 = word >> 8; + write_byte(cio, byte1); + if (byte1 == 0xFF) + write_byte(cio, 0); + byte2 = word & 0xFF; + write_byte(cio, byte2); + if (byte2 == 0xFF) + write_byte(cio, 0); + temp->len = len; + temp->val = bits.val << (16 - len); + } + else { + temp->len = 16 + len; + temp->val |= bits.val << -len; + } +} + +void +write_align_bits(compress_io *cio) +{ + BITS *temp = &(cio->temp_bits); + BITS align_bits; + align_bits.len = 8 - temp->len % 8; + align_bits.val = (UINT16) ~0x0 >> temp->len % 8; + UINT8 byte; + write_bits(cio, align_bits); + if (temp->len == 8) { + byte = temp->val >> 8; + write_byte(cio, byte); + if (byte == 0xFF) + write_byte(cio, 0); + } +} + diff --git a/LumaBmp2NinJpg/source/cio.h b/LumaBmp2NinJpg/source/cio.h new file mode 100644 index 0000000..5e3a4c6 --- /dev/null +++ b/LumaBmp2NinJpg/source/cio.h @@ -0,0 +1,36 @@ + +#ifndef __CIO_H +#define __CIO_H + +typedef bool (*CIO_METHOD) (void *); + +typedef struct { + UINT8 *set; + UINT8 *pos; + UINT8 *end; + CIO_METHOD flush_buffer; + FILE *fp; +} mem_mgr; + +typedef struct { + mem_mgr *in; + mem_mgr *out; + BITS temp_bits; +} compress_io; + + +bool flush_cin_buffer(void *cio); +bool flush_cout_buffer(void *cio); + +void init_mem(compress_io *cio, + FILE *in_fp, int in_size, FILE *out_fp, int out_size); +void free_mem(compress_io *cio); + +void write_byte(compress_io *cio, UINT8 val); +void write_word(compress_io *cio, UINT16 val); +void write_marker(compress_io *cio, JPEG_MARKER mark); +void write_bits(compress_io *cio, BITS bits); +void write_align_bits(compress_io *cio); + +#endif /* __CIO_H */ + diff --git a/LumaBmp2NinJpg/source/cjpeg.c b/LumaBmp2NinJpg/source/cjpeg.c new file mode 100644 index 0000000..c4e5019 --- /dev/null +++ b/LumaBmp2NinJpg/source/cjpeg.c @@ -0,0 +1,384 @@ +/* Copyright (C) 2009 + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + * 02111-1307, USA. + * + */ + + + +#include "cjpeg.h" +#include "cio.h" + +/* YCbCr to RGB transformation */ + +/* + * precalculated tables for a faster YCbCr->RGB transformation. + * use a INT32 table because we'll scale values by 2^16 and + * work with integers. + */ + +ycbcr_tables ycc_tables; + +void +init_ycbcr_tables() +{ + UINT16 i; + for (i = 0; i < 256; i++) { + ycc_tables.r2y[i] = (INT32)(65536 * 0.299 + 0.5) * i; + ycc_tables.r2cb[i] = (INT32)(65536 * -0.16874 + 0.5) * i; + ycc_tables.r2cr[i] = (INT32)(32768) * i; + ycc_tables.g2y[i] = (INT32)(65536 * 0.587 + 0.5) * i; + ycc_tables.g2cb[i] = (INT32)(65536 * -0.33126 + 0.5) * i; + ycc_tables.g2cr[i] = (INT32)(65536 * -0.41869 + 0.5) * i; + ycc_tables.b2y[i] = (INT32)(65536 * 0.114 + 0.5) * i; + ycc_tables.b2cb[i] = (INT32)(32768) * i; + ycc_tables.b2cr[i] = (INT32)(65536 * -0.08131 + 0.5) * i; + } +} + +void +rgb_to_ycbcr(UINT8 *rgb_unit, ycbcr_unit *ycc_unit, int x, int w) +{ + ycbcr_tables *tbl = &ycc_tables; + UINT8 r, g, b; +#ifdef REVERSED + int src_pos = (x + w * (DCTSIZE - 1)) * 3; +#else + int src_pos = x * 3; +#endif + int dst_pos = 0; + int i, j; + for (j = 0; j < DCTSIZE; j++) { + for (i = 0; i < DCTSIZE; i++) { + b = rgb_unit[src_pos]; + g = rgb_unit[src_pos+1]; + r = rgb_unit[src_pos+2]; + ycc_unit->y[dst_pos] = (INT8) ((UINT8) + ((tbl->r2y[r] + tbl->g2y[g] + tbl->b2y[b]) >> 16) - 128); + ycc_unit->cb[dst_pos] = (INT8) ((UINT8) + ((tbl->r2cb[r] + tbl->g2cb[g] + tbl->b2cb[b]) >> 16)); + ycc_unit->cr[dst_pos] = (INT8) ((UINT8) + ((tbl->r2cr[r] + tbl->g2cr[g] + tbl->b2cr[b]) >> 16)); + src_pos += 3; + dst_pos++; + } +#ifdef REVERSED + src_pos -= (w + DCTSIZE) * 3; +#else + src_pos += (w - DCTSIZE) * 3; +#endif + } +} + + +/* quantization */ + +quant_tables q_tables; + +void +init_quant_tables(UINT32 scale_factor) +{ + quant_tables *tbl = &q_tables; + int temp1, temp2; + int i; + for (i = 0; i < DCTSIZE2; i++) { + temp1 = ((UINT32) STD_LU_QTABLE[i] * scale_factor + 50) / 100; + if (temp1 < 1) + temp1 = 1; + if (temp1 > 255) + temp1 = 255; + tbl->lu[ZIGZAG[i]] = (UINT8) temp1; + + temp2 = ((UINT32) STD_CH_QTABLE[i] * scale_factor + 50) / 100; + if (temp2 < 1) + temp2 = 1; + if (temp2 > 255) + temp2 = 255; + tbl->ch[ZIGZAG[i]] = (UINT8) temp2; + } +} + +void +jpeg_quant(ycbcr_unit *ycc_unit, quant_unit *q_unit) +{ + quant_tables *tbl = &q_tables; + float q_lu, q_ch; + int x, y, i = 0; + for (x = 0; x < DCTSIZE; x++) { + for (y = 0; y < DCTSIZE; y++) { + q_lu = 1.0 / ((double) tbl->lu[ZIGZAG[i]] * \ + AAN_SCALE_FACTOR[x] * AAN_SCALE_FACTOR[y] * 8.0); + q_ch = 1.0 / ((double) tbl->ch[ZIGZAG[i]] * \ + AAN_SCALE_FACTOR[x] * AAN_SCALE_FACTOR[y] * 8.0); + + q_unit->y[i] = (INT16)(ycc_unit->y[i]*q_lu + 16384.5) - 16384; + q_unit->cb[i] = (INT16)(ycc_unit->cb[i]*q_ch + 16384.5) - 16384; + q_unit->cr[i] = (INT16)(ycc_unit->cr[i]*q_ch + 16384.5) - 16384; + + i++; + } + } +} + + +/* huffman compression */ + +huff_tables h_tables; + +void +set_huff_table(UINT8 *nrcodes, UINT8 *values, BITS *h_table) +{ + int i, j, k; + j = 0; + UINT16 value = 0; + for (i = 1; i <= 16; i++) { + for (k = 0; k < nrcodes[i]; k++) { + h_table[values[j]].len = i; + h_table[values[j]].val = value; + j++; + value++; + } + value <<= 1; + } +} + +void +init_huff_tables() +{ + huff_tables *tbl = &h_tables; + set_huff_table(STD_LU_DC_NRCODES, STD_LU_DC_VALUES, tbl->lu_dc); + set_huff_table(STD_LU_AC_NRCODES, STD_LU_AC_VALUES, tbl->lu_ac); + set_huff_table(STD_CH_DC_NRCODES, STD_CH_DC_VALUES, tbl->ch_dc); + set_huff_table(STD_CH_AC_NRCODES, STD_CH_AC_VALUES, tbl->ch_ac); +} + +void +set_bits(BITS *bits, INT16 data) +{ + UINT16 pos_data; + int i; + pos_data = data < 0 ? ~data + 1 : data; + for (i = 15; i >= 0; i--) + if ((pos_data & (1 << i)) != 0) + break; + bits->len = i + 1; + bits->val = data < 0 ? data + (1 << bits->len) - 1 : data; +} + +#ifdef DEBUG +void +print_bits(BITS bits) +{ + printf("%hu %hu\t", bits.len, bits.val); +} +#endif + +/* + * compress JPEG + */ +void +jpeg_compress(compress_io *cio, + INT16 *data, INT16 *dc, BITS *dc_htable, BITS *ac_htable) +{ + INT16 zigzag_data[DCTSIZE2]; + BITS bits; + INT16 diff; + int i, j; + int zero_num; + int mark; + + /* zigzag encode */ + for (i = 0; i < DCTSIZE2; i++) + zigzag_data[ZIGZAG[i]] = data[i]; + + /* write DC */ + diff = zigzag_data[0] - *dc; + *dc = zigzag_data[0]; + + if (diff == 0) + write_bits(cio, dc_htable[0]); + else { + set_bits(&bits, diff); + write_bits(cio, dc_htable[bits.len]); + write_bits(cio, bits); + } + + /* write AC */ + int end = DCTSIZE2 - 1; + while (zigzag_data[end] == 0 && end > 0) + end--; + for (i = 1; i <= end; i++) { + j = i; + while (zigzag_data[j] == 0 && j <= end) + j++; + zero_num = j - i; + for (mark = 0; mark < zero_num / 16; mark++) + write_bits(cio, ac_htable[0xF0]); + zero_num = zero_num % 16; + set_bits(&bits, zigzag_data[j]); + write_bits(cio, ac_htable[zero_num * 16 + bits.len]); + write_bits(cio, bits); + i = j; + } + + /* write end of unit */ + if (end != DCTSIZE2 - 1) + write_bits(cio, ac_htable[0]); +} + + +/* + * main JPEG encoding + */ +void +jpeg_encode(compress_io *cio, bmp_info *binfo) +{ + /* init tables */ + UINT32 scale = 50; + init_ycbcr_tables(); + init_quant_tables(scale); + init_huff_tables(); + + /* write info */ + write_file_header(cio); + write_frame_header(cio, binfo); + write_scan_header(cio); + + /* encode */ + mem_mgr *in = cio->in; + ycbcr_unit ycc_unit; + quant_unit q_unit; + INT16 dc_y = 0, + dc_cb = 0, + dc_cr = 0; + int x, y; + +#ifdef REVERSED + int in_size = in->end - in->set; + int offset = binfo->offset + (binfo->datasize/in_size - 1) * in_size; +#else + int offset = binfo->offset; +#endif + fseek(in->fp, offset, SEEK_SET); + + for (y = 0; y < binfo->height; y += 8) { + + /* flush input buffer */ + if (! (in->flush_buffer) (cio)) + err_exit(BUFFER_READ_ERR); + + for (x = 0; x < binfo->width; x += 8) { + + /* convert RGB unit to YCbCr unit */ + rgb_to_ycbcr(in->set, &ycc_unit, x, binfo->width); + + /* forward DCT on YCbCr unit */ + jpeg_fdct(ycc_unit.y); + jpeg_fdct(ycc_unit.cb); + jpeg_fdct(ycc_unit.cr); + + /* quantization, store in quant unit */ + jpeg_quant(&ycc_unit, &q_unit); + + /* huffman compression, write */ + jpeg_compress(cio, q_unit.y, &dc_y, + h_tables.lu_dc, h_tables.lu_ac); + jpeg_compress(cio, q_unit.cb,&dc_cb, + h_tables.ch_dc, h_tables.ch_ac); + jpeg_compress(cio, q_unit.cr,&dc_cr, + h_tables.ch_dc, h_tables.ch_ac); + } + } + write_align_bits(cio); + + /* write file end */ + write_file_trailer(cio); +} + + + +bool +is_bmp(FILE *fp) +{ + UINT8 marker[3]; + if (fread(marker, sizeof(UINT16), 2, fp) != 2) + err_exit(FILE_READ_ERR); + if (marker[0] != 0x42 || marker[1] != 0x4D) + return false; + rewind(fp); + return true; +} + +void +err_exit(const char *error_string, int exit_num) +{ + printf(error_string); + exit(exit_num); +} + + +void +print_help() +{ + printf("compress BMP file into JPEG file.\n"); + printf("Usage:\n"); + printf(" cjpeg {BMP} {JPEG}\n"); + printf("\n"); + printf("Author: Yu, Le \n"); +} + + +#ifdef main_lib +int main(int argc, char *argv[]) +{ + if (argc == 3) { + /* open bmp file */ + FILE *bmp_fp = fopen(argv[1], "rb"); + if (!bmp_fp) + err_exit(FILE_OPEN_ERR); + if (!is_bmp(bmp_fp)) + err_exit(FILE_TYPE_ERR); + + /* open jpeg file */ + FILE *jpeg_fp = fopen(argv[2], "wb"); + if (!jpeg_fp) + err_exit(FILE_OPEN_ERR); + + /* get bmp info */ + bmp_info binfo; + read_bmp(bmp_fp, &binfo); + + /* init memory for input and output */ + compress_io cio; + int in_size = (binfo.width * 3 + 3) / 4 * 4 * DCTSIZE; + int out_size = MEM_OUT_SIZE; + init_mem(&cio, bmp_fp, in_size, jpeg_fp, out_size); + + /* main encode process */ + jpeg_encode(&cio, &binfo); + + /* flush and free memory, close files */ + if (! (cio.out->flush_buffer) (&cio)) + err_exit(BUFFER_WRITE_ERR); + free_mem(&cio); + fclose(bmp_fp); + fclose(jpeg_fp); + } + else + print_help(); + exit(0); +} +#endif // main_lib diff --git a/LumaBmp2NinJpg/source/cjpeg.h b/LumaBmp2NinJpg/source/cjpeg.h new file mode 100644 index 0000000..adbd1ce --- /dev/null +++ b/LumaBmp2NinJpg/source/cjpeg.h @@ -0,0 +1,310 @@ + +#ifndef __CJPEG_H +#define __CJPEG_H + +#include +#include +#include + +typedef unsigned char UINT8; +typedef unsigned short UINT16; +typedef unsigned int UINT32; + +typedef char INT8; +typedef short INT16; +typedef int INT32; + +//typedef unsigned char bool; /* no bool type in C */ +//#define true 1; +//#define false 0; + + +#define FILE_TYPE_ERR "file type error", 1 +#define FILE_OPEN_ERR "fopen: open file error", 2 +#define FILE_READ_ERR "fread: read file error", 3 +#define BUFFER_ALLOC_ERR "malloc: alloc buffer error", 4 +#define BUFFER_READ_ERR "fread: read buffer error", 5 +#define BUFFER_WRITE_ERR "fwrite: write buffer error", 6 + + +#define REVERSED /* regularly, BMP image is stored reversely */ + +#define MEM_OUT_SIZE 1 << 17 /* alloc output memory with 128 KB */ +#define BMP_HEAD_LEN 54 /* file head length of BMP image */ +#define COMP_NUM 3 /* number of components */ +#define PRECISION 8 /* data precision */ +#define DCTSIZE 8 /* data unit size */ +#define DCTSIZE2 64 /* data unit value number */ + + +typedef enum { /* JPEG marker codes */ + M_SOF0 = 0xc0, + M_SOF1 = 0xc1, + M_SOF2 = 0xc2, + M_SOF3 = 0xc3, + + M_SOF5 = 0xc5, + M_SOF6 = 0xc6, + M_SOF7 = 0xc7, + + M_JPG = 0xc8, + M_SOF9 = 0xc9, + M_SOF10 = 0xca, + M_SOF11 = 0xcb, + + M_SOF13 = 0xcd, + M_SOF14 = 0xce, + M_SOF15 = 0xcf, + + M_DHT = 0xc4, + + M_DAC = 0xcc, + + M_RST0 = 0xd0, + M_RST1 = 0xd1, + M_RST2 = 0xd2, + M_RST3 = 0xd3, + M_RST4 = 0xd4, + M_RST5 = 0xd5, + M_RST6 = 0xd6, + M_RST7 = 0xd7, + + M_SOI = 0xd8, + M_EOI = 0xd9, + M_SOS = 0xda, + M_DQT = 0xdb, + M_DNL = 0xdc, + M_DRI = 0xdd, + M_DHP = 0xde, + M_EXP = 0xdf, + + M_APP0 = 0xe0, + M_APP1 = 0xe1, + M_APP2 = 0xe2, + M_APP3 = 0xe3, + M_APP4 = 0xe4, + M_APP5 = 0xe5, + M_APP6 = 0xe6, + M_APP7 = 0xe7, + M_APP8 = 0xe8, + M_APP9 = 0xe9, + M_APP10 = 0xea, + M_APP11 = 0xeb, + M_APP12 = 0xec, + M_APP13 = 0xed, + M_APP14 = 0xee, + M_APP15 = 0xef, + + M_JPG0 = 0xf0, + M_JPG13 = 0xfd, + M_COM = 0xfe, + + M_TEM = 0x01, + + M_ERROR = 0x100 +} JPEG_MARKER; + + +typedef struct { + UINT8 len; + UINT16 val; +} BITS; + + +/* zigzag table */ + +static UINT8 ZIGZAG[DCTSIZE2] = { + 0, 1, 5, 6, 14, 15, 27, 28, + 2, 4, 7, 13, 16, 26, 29, 42, + 3, 8, 12, 17, 25, 30, 41, 43, + 9, 11, 18, 24, 31, 40, 44, 53, + 10, 19, 23, 32, 39, 45, 52, 54, + 20, 22, 33, 38, 46, 51, 55, 60, + 21, 34, 37, 47, 50, 56, 59, 61, + 35, 36, 48, 49, 57, 58, 62, 63 +}; + + +/* RGB to YCbCr table */ + +typedef struct { + INT32 r2y[256]; + INT32 r2cb[256]; + INT32 r2cr[256]; + INT32 g2y[256]; + INT32 g2cb[256]; + INT32 g2cr[256]; + INT32 b2y[256]; + INT32 b2cb[256]; + INT32 b2cr[256]; +} ycbcr_tables; + +extern ycbcr_tables ycc_tables; + +/* store color unit in YCbCr */ + +typedef struct { + float y[DCTSIZE2]; + float cb[DCTSIZE2]; + float cr[DCTSIZE2]; +} ycbcr_unit; + + +/* standard quantization tables */ + +static UINT8 STD_LU_QTABLE[DCTSIZE2] = { /* luminance */ + 16, 11, 10, 16, 24, 40, 51, 61, + 12, 12, 14, 19, 26, 58, 60, 55, + 14, 13, 16, 24, 40, 57, 69, 56, + 14, 17, 22, 29, 51, 87, 80, 62, + 18, 22, 37, 56, 68, 109, 103, 77, + 24, 35, 55, 64, 81, 104, 113, 92, + 49, 64, 78, 87, 103, 121, 120, 101, + 72, 92, 95, 98, 112, 100, 103, 99 +}; + +static UINT8 STD_CH_QTABLE[DCTSIZE2] = { /* chrominance */ + 17, 18, 24, 47, 99, 99, 99, 99, + 18, 21, 26, 66, 99, 99, 99, 99, + 24, 26, 56, 99, 99, 99, 99, 99, + 47, 66, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99, + 99, 99, 99, 99, 99, 99, 99, 99 +}; + +static double AAN_SCALE_FACTOR[DCTSIZE] = { + 1.0, + 1.387039845, + 1.306562965, + 1.175875602, + 1.0, + 0.785694958, + 0.541196100, + 0.275899379 +}; + +/* store scaled quantization tables */ + +typedef struct { + UINT8 lu[DCTSIZE2]; + UINT8 ch[DCTSIZE2]; +} quant_tables; + +extern quant_tables q_tables; + +/* store color unit after quantizing operation */ + +typedef struct { + INT16 y[DCTSIZE2]; + INT16 cb[DCTSIZE2]; + INT16 cr[DCTSIZE2]; +} quant_unit; + + +/* standard huffman tables */ + +/* luminance DC */ + +static UINT8 STD_LU_DC_NRCODES[17] = { /* code No. */ + 0, 0, 1, 5, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0}; + +static UINT8 STD_LU_DC_VALUES[12] = { /* code value */ + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}; + +/* chrominance DC */ + +static UINT8 STD_CH_DC_NRCODES[17] = { + 0, 0, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0}; + +static UINT8 STD_CH_DC_VALUES[12] = { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}; + +/* luminance AC */ + +static UINT8 STD_LU_AC_NRCODES[17] = { + 0, 0, 2, 1, 3, 3, 2, 4, 3, 5, 5, 4, 4, 0, 0, 1, 0x7d}; + +static UINT8 STD_LU_AC_VALUES[162] = { + 0x01, 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12, + 0x21, 0x31, 0x41, 0x06, 0x13, 0x51, 0x61, 0x07, + 0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xa1, 0x08, + 0x23, 0x42, 0xb1, 0xc1, 0x15, 0x52, 0xd1, 0xf0, + 0x24, 0x33, 0x62, 0x72, 0x82, 0x09, 0x0a, 0x16, + 0x17, 0x18, 0x19, 0x1a, 0x25, 0x26, 0x27, 0x28, + 0x29, 0x2a, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, + 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, + 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, + 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, + 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, + 0x7a, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, + 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, + 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, + 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, + 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, 0xc5, + 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4, + 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xe1, 0xe2, + 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, + 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, + 0xf9, 0xfa +}; + +/* chrominance AC */ + +static UINT8 STD_CH_AC_NRCODES[17] = { + 0, 0, 2, 1, 2, 4, 4, 3, 4, 7, 5, 4, 4, 0, 1, 2, 0x77}; + +static UINT8 STD_CH_AC_VALUES[162] = { + 0x00, 0x01, 0x02, 0x03, 0x11, 0x04, 0x05, 0x21, + 0x31, 0x06, 0x12, 0x41, 0x51, 0x07, 0x61, 0x71, + 0x13, 0x22, 0x32, 0x81, 0x08, 0x14, 0x42, 0x91, + 0xa1, 0xb1, 0xc1, 0x09, 0x23, 0x33, 0x52, 0xf0, + 0x15, 0x62, 0x72, 0xd1, 0x0a, 0x16, 0x24, 0x34, + 0xe1, 0x25, 0xf1, 0x17, 0x18, 0x19, 0x1a, 0x26, + 0x27, 0x28, 0x29, 0x2a, 0x35, 0x36, 0x37, 0x38, + 0x39, 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, + 0x49, 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, + 0x59, 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, + 0x69, 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, + 0x79, 0x7a, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, + 0x88, 0x89, 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, + 0x97, 0x98, 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, + 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, + 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, + 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, + 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, + 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, + 0xea, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, + 0xf9, 0xfa +}; + +/* store precalculated huffman tables */ + +typedef struct { + BITS lu_dc[12]; + BITS lu_ac[256]; + BITS ch_dc[12]; + BITS ch_ac[256]; +} huff_tables; + +extern huff_tables h_tables; + + +/* store BMP image informations */ + +typedef struct { + UINT32 size; /* bmp file size: 2- 5 */ + UINT32 offset; /* offset between file start and data: 10-13 */ + UINT32 width; /* pixel width of bmp image: 18-21 */ + UINT32 height; /* pixel height of bmp image: 22-25 */ + UINT16 bitppx; /* bit number per pixel: 28-29 */ + UINT32 datasize; /* image data size: 34-37 */ +} bmp_info; + + +extern void err_exit(const char *error_string, int exit_num); + + +#endif /* __CJPEG_H */ + diff --git a/LumaBmp2NinJpg/source/cmarker.c b/LumaBmp2NinJpg/source/cmarker.c new file mode 100644 index 0000000..f619d72 --- /dev/null +++ b/LumaBmp2NinJpg/source/cmarker.c @@ -0,0 +1,232 @@ +/* Copyright (C) 2009 + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + * 02111-1307, USA. + * + */ + + + +#include "cjpeg.h" +#include "cio.h" + +/* + * Length of APP0 block (2 bytes) + * Block ID (4 bytes - ASCII "JFIF") + * Zero byte (1 byte to terminate the ID string) + * Version Major, Minor (2 bytes - major first) + * Units (1 byte - 0x00 = none, 0x01 = inch, 0x02 = cm) + * Xdpu (2 bytes - dots per unit horizontal) + * Ydpu (2 bytes - dots per unit vertical) + * Thumbnail X size (1 byte) + * Thumbnail Y size (1 byte) + */ +void +write_app0(compress_io *cio) +{ + write_marker(cio, M_APP0); + write_word(cio, 2 + 4 + 1 + 2 + 1 + 2 + 2 + 1 + 1); /* length */ + write_byte(cio, 0x4A); /* Identifier: ASCII "JFIF" */ + write_byte(cio, 0x46); + write_byte(cio, 0x49); + write_byte(cio, 0x46); + write_byte(cio, 0); + write_byte(cio, 1); /* Version fields */ + write_byte(cio, 1); + write_byte(cio, 0); /* Pixel size information */ + write_word(cio, 1); + write_word(cio, 1); + write_byte(cio, 0); /* No thumbnail image */ + write_byte(cio, 0); +} + +void +write_sof0(compress_io *cio, bmp_info *binfo) +{ + write_marker(cio, M_SOF0); + write_word(cio, 3 * COMP_NUM + 2 + 5 + 1); /* length */ + write_byte(cio, PRECISION); + + write_word(cio, binfo->height); + write_word(cio, binfo->width); + + write_byte(cio, COMP_NUM); + + /* + * Component: + * Component ID + * Sampling factors: bit 0-3 vert., 4-7 hor. + * Quantization table No. + */ + /* component Y */ + write_byte(cio, 1); + write_byte(cio, 0x11); + write_byte(cio, 0); + /* component Cb */ + write_byte(cio, 2); + write_byte(cio, 0x11); + write_byte(cio, 1); + /* component Cr */ + write_byte(cio, 3); + write_byte(cio, 0x11); + write_byte(cio, 1); +} + +void +write_sos(compress_io *cio) +{ + write_marker(cio, M_SOS); + write_word(cio, 2 + 1 + COMP_NUM * 2 + 3); /* length */ + + write_byte(cio, COMP_NUM); + + /* + * Component: + * Component ID + * DC & AC table No. bits 0..3: AC table (0..3), + * bits 4..7: DC table (0..3) + */ + /* component Y */ + write_byte(cio, 1); + write_byte(cio, 0x00); + /* component Cb */ + write_byte(cio, 2); + write_byte(cio, 0x11); + /* component Cr */ + write_byte(cio, 3); + write_byte(cio, 0x11); + + write_byte(cio, 0); /* Ss */ + write_byte(cio, 0x3F); /* Se */ + write_byte(cio, 0); /* Bf */ +} + +void +write_dqt(compress_io *cio) +{ + /* index: + * bit 0..3: number of QT, Y = 0 + * bit 4..7: precision of QT, 0 = 8 bit + */ + int index; + int i; + write_marker(cio, M_DQT); + write_word(cio, 2 + (DCTSIZE2 + 1) * 2); + + index = 0; /* table for Y */ + write_byte(cio, index); + for (i = 0; i < DCTSIZE2; i++) + write_byte(cio, q_tables.lu[i]); + + index = 1; /* table for Cb,Cr */ + write_byte(cio, index); + for (i = 0; i < DCTSIZE2; i++) + write_byte(cio, q_tables.ch[i]); +} + +int +get_ht_length(UINT8 *nrcodes) +{ + int length = 0; + int i; + for (i = 1; i <= 16; i++) + length += nrcodes[i]; + return length; +} + +void +write_htable(compress_io *cio, + UINT8 *nrcodes, UINT8 *values, int len, UINT8 index) +{ + /* + * index: + * bit 0..3: number of HT (0..3), for Y = 0 + * bit 4 : type of HT, 0 = DC table, 1 = AC table + * bit 5..7: not used, must be 0 + */ + write_byte(cio, index); + + int i; + for (i = 1; i <= 16; i++) + write_byte(cio, nrcodes[i]); + for (i = 0; i < len; i++) + write_byte(cio, values[i]); +} + +void +write_dht(compress_io *cio) +{ + int len1, len2, len3, len4; + + write_marker(cio, M_DHT); + + len1 = get_ht_length(STD_LU_DC_NRCODES); + len2 = get_ht_length(STD_LU_AC_NRCODES); + len3 = get_ht_length(STD_CH_DC_NRCODES); + len4 = get_ht_length(STD_CH_AC_NRCODES); + write_word(cio, 2 + (1 + 16) * 4 + len1 + len2 + len3 + len4); + + write_htable(cio, STD_LU_DC_NRCODES, STD_LU_DC_VALUES, len1, 0x00); + write_htable(cio, STD_LU_AC_NRCODES, STD_LU_AC_VALUES, len2, 0x10); + write_htable(cio, STD_CH_DC_NRCODES, STD_CH_DC_VALUES, len3, 0x01); + write_htable(cio, STD_CH_AC_NRCODES, STD_CH_AC_VALUES, len4, 0x11); +} + +/* + * Write datastream header. + * This consists of an SOI and optional APPn markers. + */ +void +write_file_header(compress_io *cio) +{ + write_marker(cio, M_SOI); + write_app0(cio); +} + +/* + * Write frame header. + * This consists of DQT and SOFn markers. + * Note that we do not emit the SOF until we have emitted the DQT(s). + * This avoids compatibility problems with incorrect implementations that + * try to error-check the quant table numbers as soon as they see the SOF. + */ +void +write_frame_header(compress_io *cio, bmp_info *binfo) +{ + write_dqt(cio); + write_sof0(cio, binfo); +} + +/* + * Write scan header. + * This consists of DHT or DAC markers, optional DRI, and SOS. + * Compressed data will be written following the SOS. + */ +void +write_scan_header(compress_io *cio) +{ + write_dht(cio); + write_sos(cio); +} + +/* + * Write datastream trailer. + */ +void +write_file_trailer(compress_io *cio) +{ + write_marker(cio, M_EOI); +} + diff --git a/LumaBmp2NinJpg/source/fdctflt.c b/LumaBmp2NinJpg/source/fdctflt.c new file mode 100644 index 0000000..d9ac71d --- /dev/null +++ b/LumaBmp2NinJpg/source/fdctflt.c @@ -0,0 +1,124 @@ + + +/* + * This module is specialized to the case DCTSIZE = 8. + */ + +#include "cjpeg.h" + +/* + * Perform the forward DCT on one block of samples. + */ + +void +jpeg_fdct(float *data) +{ + float tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7; + float tmp10, tmp11, tmp12, tmp13; + float z1, z2, z3, z4, z5, z11, z13; + float *dataptr; + int ctr; + + /* Pass 1: process rows. */ + + dataptr = data; + for (ctr = 0; ctr < DCTSIZE; ctr++) { + /* Load data into workspace */ + tmp0 = dataptr[0] + dataptr[7]; + tmp7 = dataptr[0] - dataptr[7]; + tmp1 = dataptr[1] + dataptr[6]; + tmp6 = dataptr[1] - dataptr[6]; + tmp2 = dataptr[2] + dataptr[5]; + tmp5 = dataptr[2] - dataptr[5]; + tmp3 = dataptr[3] + dataptr[4]; + tmp4 = dataptr[3] - dataptr[4]; + + /* Even part */ + + tmp10 = tmp0 + tmp3; /* phase 2 */ + tmp13 = tmp0 - tmp3; + tmp11 = tmp1 + tmp2; + tmp12 = tmp1 - tmp2; + + /* Apply unsigned->signed conversion */ + dataptr[0] = tmp10 + tmp11; /* phase 3 */ + dataptr[4] = tmp10 - tmp11; + + z1 = (tmp12 + tmp13) * ((float) 0.707106781); /* c4 */ + dataptr[2] = tmp13 + z1; /* phase 5 */ + dataptr[6] = tmp13 - z1; + + /* Odd part */ + + tmp10 = tmp4 + tmp5; /* phase 2 */ + tmp11 = tmp5 + tmp6; + tmp12 = tmp6 + tmp7; + + /* The rotator is modified from fig 4-8 to avoid extra negations. */ + z5 = (tmp10 - tmp12) * ((float) 0.382683433); /* c6 */ + z2 = ((float) 0.541196100) * tmp10 + z5; /* c2-c6 */ + z4 = ((float) 1.306562965) * tmp12 + z5; /* c2+c6 */ + z3 = tmp11 * ((float) 0.707106781); /* c4 */ + + z11 = tmp7 + z3; /* phase 5 */ + z13 = tmp7 - z3; + + dataptr[5] = z13 + z2; /* phase 6 */ + dataptr[3] = z13 - z2; + dataptr[1] = z11 + z4; + dataptr[7] = z11 - z4; + + dataptr += DCTSIZE; /* advance pointer to next row */ + } + + /* Pass 2: process columns. */ + + dataptr = data; + for (ctr = DCTSIZE-1; ctr >= 0; ctr--) { + tmp0 = dataptr[DCTSIZE*0] + dataptr[DCTSIZE*7]; + tmp7 = dataptr[DCTSIZE*0] - dataptr[DCTSIZE*7]; + tmp1 = dataptr[DCTSIZE*1] + dataptr[DCTSIZE*6]; + tmp6 = dataptr[DCTSIZE*1] - dataptr[DCTSIZE*6]; + tmp2 = dataptr[DCTSIZE*2] + dataptr[DCTSIZE*5]; + tmp5 = dataptr[DCTSIZE*2] - dataptr[DCTSIZE*5]; + tmp3 = dataptr[DCTSIZE*3] + dataptr[DCTSIZE*4]; + tmp4 = dataptr[DCTSIZE*3] - dataptr[DCTSIZE*4]; + + /* Even part */ + + tmp10 = tmp0 + tmp3; /* phase 2 */ + tmp13 = tmp0 - tmp3; + tmp11 = tmp1 + tmp2; + tmp12 = tmp1 - tmp2; + + dataptr[DCTSIZE*0] = tmp10 + tmp11; /* phase 3 */ + dataptr[DCTSIZE*4] = tmp10 - tmp11; + + z1 = (tmp12 + tmp13) * ((float) 0.707106781); /* c4 */ + dataptr[DCTSIZE*2] = tmp13 + z1; /* phase 5 */ + dataptr[DCTSIZE*6] = tmp13 - z1; + + /* Odd part */ + + tmp10 = tmp4 + tmp5; /* phase 2 */ + tmp11 = tmp5 + tmp6; + tmp12 = tmp6 + tmp7; + + /* The rotator is modified from fig 4-8 to avoid extra negations. */ + z5 = (tmp10 - tmp12) * ((float) 0.382683433); /* c6 */ + z2 = ((float) 0.541196100) * tmp10 + z5; /* c2-c6 */ + z4 = ((float) 1.306562965) * tmp12 + z5; /* c2+c6 */ + z3 = tmp11 * ((float) 0.707106781); /* c4 */ + + z11 = tmp7 + z3; /* phase 5 */ + z13 = tmp7 - z3; + + dataptr[DCTSIZE*5] = z13 + z2; /* phase 6 */ + dataptr[DCTSIZE*3] = z13 - z2; + dataptr[DCTSIZE*1] = z11 + z4; + dataptr[DCTSIZE*7] = z11 - z4; + + dataptr++; /* advance pointer to next column */ + } +} + diff --git a/LumaBmp2NinJpg/source/main.c b/LumaBmp2NinJpg/source/main.c new file mode 100644 index 0000000..b59b84a --- /dev/null +++ b/LumaBmp2NinJpg/source/main.c @@ -0,0 +1,516 @@ +#include +#include +#include +#include +#include +#include +//#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(); +} diff --git a/LumaBmp2NinJpg/source/rdbmp.c b/LumaBmp2NinJpg/source/rdbmp.c new file mode 100644 index 0000000..9214301 --- /dev/null +++ b/LumaBmp2NinJpg/source/rdbmp.c @@ -0,0 +1,50 @@ + +#include "cjpeg.h" + +UINT32 +extract_uint(const UINT8 *dataptr, UINT32 start, UINT32 len) +{ + UINT32 uint = 0; + if (len <= 0 || len > 4) + return uint; + if (len > 0) + uint += dataptr[start]; + if (len > 1) + uint += dataptr[start+1] * 1 << 8; + if (len > 2) + uint += dataptr[start+2] * 1 << 16; + if (len > 3) + uint += dataptr[start+3] * 1 << 24; + return uint; +} + +int +get_file_size(FILE *bmp_fp) +{ + fpos_t fpos; + int len; + fgetpos(bmp_fp, &fpos); + fseek(bmp_fp, 0, SEEK_END); + len = ftell(bmp_fp); + fsetpos(bmp_fp, &fpos); + return len; +} + +void +read_bmp(FILE *bmp_fp, bmp_info *binfo) +{ + size_t len = BMP_HEAD_LEN; + UINT8 bmp_head[len]; + if (fread(bmp_head, sizeof (UINT8), len, bmp_fp) != len) + err_exit(FILE_READ_ERR); + + binfo->size = extract_uint(bmp_head, 2, 4); + binfo->offset = extract_uint(bmp_head, 10, 4); + binfo->width = extract_uint(bmp_head, 18, 4); + binfo->height = extract_uint(bmp_head, 22, 4); + binfo->bitppx = extract_uint(bmp_head, 28, 2); + binfo->datasize = extract_uint(bmp_head, 34, 4); + if (binfo->datasize == 0) /* data size not included in some BMP */ + binfo->datasize = get_file_size(bmp_fp) - binfo->offset; +} +