I saw some dude on ps2dev try to submit a sample of how to use scejpeg but got rejected because of the use of libraries not in the official sdk.
I decided to check it out.
and made my own sample
main.c
#include <pspkernel.h>
#include <pspdebug.h>
#include <pspsdk.h>
#include <stdlib.h>
#include <stdio.h>
#include <pspdisplay.h>
#include <psputility.h>
#include <pspjpeg.h>
#include "graphics.h"
#define printf pspDebugScreenPrintf
PSP_MODULE_INFO("JpegSample", PSP_MODULE_USER, 1, 1);
PSP_HEAP_SIZE_KB(-1024);
//extern int getNextPower2(int width);
int getNextPower2(int width)
{
int b = width;
int n;
for (n = 0; b != 0; n++) b >>= 1;
b = 1 << n;
if (b == 2 * width) b >>= 1;
return b;
}
/* Exit callback */
int exit_callback(int arg1, int arg2, void *common)
{
sceKernelExitGame();
return 0;
}
/* Callback thread */
int CallbackThread(SceSize args, void *argp)
{
int cbid;
cbid = sceKernelCreateCallback("Exit Callback", exit_callback, NULL);
sceKernelRegisterExitCallback(cbid);
sceKernelSleepThreadCB();
return 0;
}
/* Sets up the callback thread and returns its thread id */
int SetupCallbacks(void)
{
int thid = 0;
thid = sceKernelCreateThread("update_thread", CallbackThread, 0x11, 0xFA0, 0, 0);
if(thid >= 0)
{
sceKernelStartThread(thid, 0, 0);
}
return thid;
}
int getJpegDimensions(u8* data, int data_size, int *width, int *height){
int i = 0;
if (data[i] == 0xFF && data[i+1] == 0xD8 && data[i+2] == 0xFF && data[i+3] == 0xE0) {
i += 4;
// Check for valid JPEG header (null terminated JFIF)
if (data[i+2] == 'J' && data[i+3] == 'F' && data[i+4] == 'I' && data[i+5] == 'F' && data[i+6] == 0x00){
//Retrieve the block length of the first block since the first block will not contain the size of file
int block_length = data[i] * 256 + data[i+1];
while (i < data_size){
i += block_length; //Increase the file index to get to the next block
if (i >= data_size) return -1; //Check to protect against segmentation faults
if (data[i] != 0xFF) return -1; //Check that we are truly at the start of another block
if (data[i+1] == 0xC0) { //0xFFC0 is the "Start of frame" marker which contains the file size
//The structure of the 0xFFC0 block is quite simple [0xFFC0][ushort length][uchar precision][ushort x][ushort y]
*height = data[i+5]*256 + data[i+6];
*width = data[i+7]*256 + data[i+8];
return 0;
}
else{
i += 2; //Skip the block marker
block_length = data[i] * 256 + data[i+1]; //Go to the next block
}
}
return -1; //If this point is reached then no size was found
}
else
return -1; //Not a valid JFIF string
}
else
return -1; //Not a valid SOI header
}
int main(int argc, char *argv[]){
SetupCallbacks();
pspDebugScreenInit();
int ret;
if (sceUtilityLoadAvModule(PSP_AV_MODULE_AVCODEC) < 0) sceKernelExitGame();
ret = sceJpegInitMJpeg();
if (ret < 0){
printf("sceJpegInitMJpeg %d\n", ret);
sceUtilityUnloadAvModule(PSP_AV_MODULE_AVCODEC);
sceKernelDelayThread(5000000);
sceKernelExitGame();
}
SceUID fd;
u8 *data;
int size;
fd = sceIoOpen("sample.jpg", PSP_O_RDONLY, 0777);
if (fd < 0){
printf("sceIoOpen 0x%x\n", fd);
sceUtilityUnloadAvModule(PSP_AV_MODULE_AVCODEC);
sceKernelDelayThread(5000000);
sceKernelExitGame();
}
size = sceIoLseek32(fd, 0, PSP_SEEK_END);
if (size < 0){
printf("sceIoOpen 0x%x\n", ret);
sceIoClose(fd);
sceUtilityUnloadAvModule(PSP_AV_MODULE_AVCODEC);
sceKernelDelayThread(5000000);
sceKernelExitGame();
}
sceIoLseek32(fd, 0, PSP_SEEK_SET);
data = malloc(size);
if (!data){
printf("malloc failed\n");
sceIoClose(fd);
sceJpegFinishMJpeg();
sceUtilityUnloadAvModule(PSP_AV_MODULE_AVCODEC);
sceKernelDelayThread(5000000);
sceKernelExitGame();
}
sceIoRead(fd, data, size);
sceIoClose(fd);
int width = 480, height = 272;
if (getJpegDimensions(data, size, &width, &height) < 0){
printf("Cannot find dimensions defaulting to %dx%d\n", width, height);
}
ret = sceJpegCreateMJpeg(width, height);
if (ret < 0){
printf("sceJpegCreateMJpeg 0x%x\n", ret);
free(data);
sceJpegFinishMJpeg();
sceUtilityUnloadAvModule(PSP_AV_MODULE_AVCODEC);
sceKernelDelayThread(5000000);
sceKernelExitGame();
}
u32 *imgBuf = (u32*)memalign(64, getNextPower2(width)*getNextPower2(height)*4);
if (!imgBuf){
printf("malloc failed\nw = %d\nh = %d\n", width, height);
free(data);
sceJpegDeleteMJpeg();
sceJpegFinishMJpeg();
sceUtilityUnloadAvModule(PSP_AV_MODULE_AVCODEC);
sceKernelDelayThread(5000000);
sceKernelExitGame();
}
ret = sceJpegDecodeMJpeg(data, size, imgBuf, 0);
if (ret < 0){
printf("sceJpegDecodeMJpeg 0x%x\nw = %d\nh = %d\n", ret, width, height);
free(data);
free(imgBuf);
sceJpegDeleteMJpeg();
sceJpegFinishMJpeg();
sceUtilityUnloadAvModule(PSP_AV_MODULE_AVCODEC);
sceKernelDelayThread(5000000);
sceKernelExitGame();
}
free(data);
sceJpegDeleteMJpeg();
sceJpegFinishMJpeg();
sceUtilityUnloadAvModule(PSP_AV_MODULE_AVCODEC);
Image *img = malloc(sizeof(Image));
if (!img){
printf("malloc failed\n");
free(imgBuf);
sceKernelDelayThread(5000000);
sceKernelExitGame();
}
img->imageHeight = height;
img->imageWidth = width;
img->textureHeight = getNextPower2(height);
img->textureWidth = getNextPower2(width);
img->data = imgBuf;
int i, j;
for (i = height-1; i >= 0 ; i--)
for (j = width-1; j >= 0; j--)
imgBuf[i*img->textureWidth+j] = 0xff000000|imgBuf[i*width+j];
sceKernelDcacheWritebackInvalidateRange(imgBuf, img->textureHeight*img->textureWidth*4);
initGraphics();
blitAlphaImageToScreen(0, 0, img->imageWidth, img->imageHeight, img, 0, 0);
flipScreen();
sceKernelSleepThread();
return 0;
}
Makefile
TARGET = jpeg
OBJS = main.o graphics.o framebuffer.o
BUILD_PRX = 1
CFLAGS = -O2 -G0 -Wall -g
CXXFLAGS = $(CFLAGS) -fno-exceptions -fno-rtti
ASFLAGS = $(CFLAGS)
INCDIR =
LIBS = -lpspjpeg -lpsputility -lpng -lz -lm -lpspgu
PSP_LARGE_MEMORY = 1
EXTRA_TARGETS = EBOOT.PBP
PSP_EBOOT_TITLE = JPEG
PSPSDK=$(shell psp-config --pspsdk-path)
include $(PSPSDK)/lib/build.mak
The image data returned is not aligned to the next power of 2 and all the alpha values are 0, so I set it up to work with graphics.c/h
NOTE
note all resolutions are supported
these work(width by height)
176x144, 320x240, 640x480, 272x480, 720x480, 400x192, 144x80,
368x208This looks like a special case library for decoding camera images of something
Photoshop images fails to load.
error codes
sceJpegDecodeMJpeg
0x80650016 - ?
0x80650020 - ?
0x80650035 - invalid format?(progressive)