How can I convert JPG image to ART?

Post Reply
pjexposito
Posts: 7
Joined: Thu Jul 25, 2019 6:03 am
languages_spoken: english
ODROIDs: Odroid Go
Has thanked: 0
Been thanked: 0
Contact:

How can I convert JPG image to ART?

Post by pjexposito »

Hi.

I'm doing a python script to export all my favorites games to Odroid Go. But I've got all covert art on JPG file format. Can I convert these JPG to art? Any python script o C code?

Thanks!

konig
Posts: 33
Joined: Thu Aug 16, 2018 11:09 pm
languages_spoken: english
ODROIDs: GO
Has thanked: 0
Been thanked: 1 time
Contact:

Re: How can I convert JPG image to ART?

Post by konig »

Download GNU Image Manipulation Program (GIMP): https://www.gimp.org/downloads/

Open desired image in GIMP then click File -> Export As -> Click the dropdown and select 'C source code (*.c)' and give the file name a .c extension -> Click Export -> Tick the box labeled 'Save as RGB565 (16-bit)' -> Click Export

Open the resulting C file and scroll to the top. You will see it defines a struct and instantiates it with the image data. Of most interest is struct member 'pixel_data' which is the array of bytes representing the raw pixel data of the image

pjexposito
Posts: 7
Joined: Thu Jul 25, 2019 6:03 am
languages_spoken: english
ODROIDs: Odroid Go
Has thanked: 0
Been thanked: 0
Contact:

Re: How can I convert JPG image to ART?

Post by pjexposito »

Thank you for your help, but I finally used code from this fantastic page https://codepen.io/SarahC/full/qJNYoZ

I've converted some code to run on node.js and then I've used a python script to do all the job. It's kind of dirty but it works.

These are the two scripts:

For node.js (filename: file.js) (all credits to Sarah Cartwright)

Code: Select all

var dither_tresshold_r = [
1, 7, 3, 5, 0, 8, 2, 6,
7, 1, 5, 3, 8, 0, 6, 2,
3, 5, 0, 8, 2, 6, 1, 7,
5, 3, 8, 0, 6, 2, 7, 1,

0, 8, 2, 6, 1, 7, 3, 5,
8, 0, 6, 2, 7, 1, 5, 3,
2, 6, 1, 7, 3, 5, 0, 8,
6, 2, 7, 1, 5, 3, 8, 0];


var dither_tresshold_g = [
1, 3, 2, 2, 3, 1, 2, 2,
2, 2, 0, 4, 2, 2, 4, 0,
3, 1, 2, 2, 1, 3, 2, 2,
2, 2, 4, 0, 2, 2, 0, 4,

1, 3, 2, 2, 3, 1, 2, 2,
2, 2, 0, 4, 2, 2, 4, 0,
3, 1, 2, 2, 1, 3, 2, 2,
2, 2, 4, 0, 2, 2, 0, 4];


var dither_tresshold_b = [
5, 3, 8, 0, 6, 2, 7, 1,
3, 5, 0, 8, 2, 6, 1, 7,
8, 0, 6, 2, 7, 1, 5, 3,
0, 8, 2, 6, 1, 7, 3, 5,

6, 2, 7, 1, 5, 3, 8, 0,
2, 6, 1, 7, 3, 5, 0, 8,
7, 1, 5, 3, 8, 0, 6, 2,
1, 7, 3, 5, 0, 8, 2, 6];


const { createCanvas, loadImage } = require('canvas');
Canvas = require('canvas');
Image = Canvas.Image;
var base64Img = require('base64-img');
const jsdom = require("jsdom");
const { JSDOM } = jsdom;

const dom1 = new JSDOM();

var archivo=process.argv[2];
var file = null;
var path = require('path'),    
    filePath = path.join(__dirname, archivo);

function convertToRGB565(r, g, b) {
	  return r >> 3 << 11 | g >> 2 << 5 | b >> 3;
}
	
function calculateAspectRatioFit(srcWidth, srcHeight, maxWidth, maxHeight) {
	  var ratio = Math.min(maxWidth / srcWidth, maxHeight / srcHeight);
	  return { width: srcWidth * ratio, height: srcHeight * ratio };
}

function closest_rb(c) {
  return c >> 3 << 3; /* red & blue */
}

function closest_g(c) {
  return c >> 2 << 2; /* green */
}

function convertToRGB565(r, g, b) {
  return r >> 3 << 11 | g >> 2 << 5 | b >> 3;
}

function dither_888xy565(x, y, r, g, b) {
  let tresshold_id = ((y & 7) << 3) + (x & 7);
  let r2 = closest_rb(Math.min(r + dither_tresshold_r[tresshold_id], 0xff));
  let g2 = closest_g(Math.min(g + dither_tresshold_g[tresshold_id], 0xff));
  let b2 = closest_rb(Math.min(b + dither_tresshold_b[tresshold_id], 0xff));
  return convertToRGB565(r2, g2, b2);
}
	
function toART565(src, width, height, dither) {
		//console.log("Source:");
		//console.log(src);
	  let dest = new Uint8ClampedArray(width * height * 2 + 4);
	  //console.log(dest);
	  dest[0] = width & 0xff;
	  dest[1] = width >> 8;
	  dest[2] = height & 0xff;
	  dest[3] = height >> 8;
	  for (let y = 0; y < height; y++) {
	    for (let x = 0; x < width; x++) {
	      let ptr = y * width + x;
	      let ptrDest = ptr * 4;
	      let ptrSrc = ptr * 2 + 4;
	      let word16 = null;
	      if (dither)
	      word16 = dither_888xy565(x, y, src[ptrDest], src[ptrDest + 1], src[ptrDest + 2]);
		    else
	      word16 = convertToRGB565(src[ptrDest], src[ptrDest + 1], src[ptrDest + 2]);
	      dest[ptrSrc] = word16 & 0xff;
	      dest[ptrSrc + 1] = word16 >> 8;
	    }
	  }
	  return dest;
}

base64Img.base64(archivo, function(err, data) {

	//const dom1 = new JSDOM();
	//img = dom1.window.document.createElement("img");
	    var img = new Image();
	    img.onload = function () {
	      var c = createCanvas();
	      var ctx = c.getContext('2d')
	      ctx.imageSmoothingEnabled = true;
	      let resizedDimensions = calculateAspectRatioFit(img.width, img.height, 320, 176);
		
	      c.width = resizedDimensions.width;
	      c.height = resizedDimensions.height;		  
	  	  ctx.drawImage(img, 0, 0, resizedDimensions.width, resizedDimensions.height);
		  var datosImagen = ctx.getImageData(0, 0, c.width, c.height);
	  	  //console.log(datosImagen.data);
	      let imageData = datosImagen.data;
	      artImage = toART565(imageData, datosImagen.width, datosImagen.height, true);
		
		
		  const fs = require('fs');
		  fs.writeFile(archivo.slice(0, -4)+".art", artImage, function(err) 
		  {
		    if(err) 
			{
		        return console.log(err);
		    }
		  }); 
	    }
		img.src=data;			
})
And the Python script:

Code: Select all


#!/usr/bin/env python
# -*- coding: utf-8 -*-


import sqlite3, os, zlib, sys
from shutil import copyfile, rmtree


contador = 0
sistemas = ["a2600", "a7800", "lynx", "col", "gb", "gbc", "gg", "nes", "sms"]
numeros = ["0","1","2","3","4","5","6","7","8","9","A","B","C","D","E","F"]
        

def crea_carpetas_sistemas():
    if os.path.exists(os.getcwd()+"/romart"):
        rmtree(os.getcwd()+"/romart")
    print "Creando carpetas..."
    os.mkdir(os.getcwd()+"/romart")
    for sistema in sistemas:
       print "Creando carpeta "+sistema
       os.mkdir(os.getcwd()+"/romart/"+sistema)
       for valor in numeros:
           os.mkdir(os.getcwd()+"/romart/"+sistema+"/"+valor)
           

def crc(fileName):
    prev = 0
    for eachLine in open(fileName,"rb"):
        prev = zlib.crc32(eachLine, prev)
    return "%X"%(prev & 0xFFFFFFFF)

def crc_nes(fileName):
    buf = open(fileName,'rb')
    buf.seek(16)
    resto = buf.read()
    return "%X"%(zlib.crc32(resto) & 0xFFFFFFFF)
    
def correcto(CRC32):
    if len(CRC32) == 7:   
        return "0"+CRC32
    elif len(CRC32) == 6:
        return "00"+CRC32
    else:
        return CRC32

def devuelve_sistema(sistema,filename):
    extension = os.path.splitext(filename)[1]
    nuevo = "ND"
    if extension == ".gbc":
        nuevo = "gbc"
    elif sistema == 2:
        nuevo = "lynx"
    elif sistema == 8:
        nuevo = "nes"
    elif sistema == 9:
        nuevo = "gb"
    elif sistema == 15:
        nuevo = "a2600"
    elif sistema == 25:
        nuevo = "gg"
    elif sistema == 26:
        nuevo = "sms"
    elif sistema == 4:
        nuevo = "a7800"
    elif sistema == 22:
        nuevo = "col"

    return nuevo  
def saca_datos(CRC32,filename,sistema):
    CRC32 = correcto(CRC32)
    CRC32 = CRC32.lower()
    con_bd = sqlite3.connect('Library.storedata')
    con_bd.row_factory = sqlite3.Row
    cursor_tabla = con_bd.cursor()
    parametro = (CRC32,)
    cursor_tabla.execute("SELECT * FROM ZROM WHERE ZCRC32=?", parametro)
    registro=cursor_tabla.fetchone()
    IDJUEGO= registro['ZGAME']
    parametro = (IDJUEGO,)
    cursor_tabla.execute("SELECT * FROM ZGAME WHERE Z_PK=?", parametro)
    registro=cursor_tabla.fetchone()
    ZSYSTEM = registro['ZSYSTEM']
    ZGAMETITLE = registro['ZGAMETITLE']
    ZNAME = registro['ZNAME']
    ZSYSTEMNAME= devuelve_sistema(ZSYSTEM,filename)
    ZRATING = registro['ZRATING']
    parametro = (IDJUEGO,)
    cursor_tabla.execute("SELECT * FROM ZIMAGE WHERE ZBOX=?", parametro)
    registro=cursor_tabla.fetchone()
    try: 
        ZIMAGEN = registro['ZRELATIVEPATH']
    except:
        ZIMAGEN = "Error"
    cursor_tabla.close()
    con_bd.close()
    ruta = os.getcwd()+"/roms/"+sistema+"/"
    
    #print(CRC32, ZSYSTEMNAME, ZGAMETITLE, ZNAME, ZIMAGEN)
    if ZSYSTEMNAME == "nes":
        CRC32 = correcto(crc_nes(ruta+filename))
    if ZIMAGEN != "Error": 
        copyfile(os.getcwd()+"/Artwork/"+ZIMAGEN,os.getcwd()+"/romart/"+ZSYSTEMNAME+"/"+CRC32[0].upper()+"/"+CRC32.upper()+".jpg")
        comando = "node \""+os.getcwd()+"/file.js\" \""+os.getcwd()+"/romart/"+ZSYSTEMNAME+"/"+CRC32[0].upper()+"/"+CRC32.upper()+".jpg\""
        os.system(comando)
        os.remove(os.getcwd()+"/romart/"+ZSYSTEMNAME+"/"+CRC32[0].upper()+"/"+CRC32.upper()+".jpg")
    if int(ZRATING)>0:
        os.rename(ruta+filename,ruta+"-"+filename)
        #if not(os.path.exists(os.getcwd()+"/art/"+CRC32.upper()+".art")): 
            #print "No existe "+CRC32+" "+ZSYSTEMNAME+": "+ZGAMETITLE


archivos_totales = sum([len(files) for r, d, files in os.walk(os.getcwd()+"/roms/")])
crea_carpetas_sistemas()
for sistema in sistemas:
    ruta = os.getcwd()+"/roms/"+sistema+"/"
    for filename in os.listdir(ruta):
        CRC32 = crc(ruta+filename)
        #print filename
        if filename[0] != ".":
          saca_datos(CRC32,filename,sistema)
        contador+=1
        
        porciento = (float(contador)/float(archivos_totales))*100
        #sys.stdout.write("Procesado: %d%%   \r" % (porciento) )
        cadena = str(contador)+"/"+str(archivos_totales)+" - "+sistema
        
        sys.stdout.write("Procesado: %s  \r" % (cadena) )
        sys.stdout.flush()
        #print ("Procesado "+str(porciento)[:5]+"%")
print "Todos los archivos procesados"
print "Finalizado"


I'm using OpenEmu database and thumbnails to get all the information, by the way.

Greets

Post Reply

Return to “General Topics”

Who is online

Users browsing this forum: No registered users and 1 guest