Jump to content


olie304's Content

There have been 14 items by olie304 (Search limited from 30-March 23)


By content type

See this member's

Sort by                Order  

#276746 Image to Terminal glasses efficiency

Posted by olie304 on 10 April 2018 - 01:48 AM in Ask a Pro

View PostBomb Bloke, on 15 November 2017 - 04:17 AM, said:

Alright, I know it has been a while, forgive me. I have made a pretty solid format using the following:
File file = new File(fileName);
BufferedImage image = ImageIO.read(file);

Files.deleteIfExists(Paths.get(outputName));
FileOutputStream fileOut = new FileOutputStream(outputName);
BufferedOutputStream writer = new BufferedOutputStream(fileOut);

writer.write(1); //1 Volume (Future Implementation)
writer.write(image.getHeight() &  255);
writer.write((image.getHeight() >> 8) & 255);
writer.write(image.getWidth() & 255);
writer.write((image.getWidth() >> 8) & 255);

int[][] lengths = new int[image.getHeight()][image.getWidth()];
for (int y = 0; y < image.getHeight(); y++) {
for (int x = 0; x < image.getWidth(); x++) {
  int leng = 1;
  while (x + leng < image.getWidth() && image.getRGB(x, y) == image.getRGB(x + leng, y)) {
   leng++;
  }
  lengths[y][x] = leng;
  x += leng - 1;
}
}

//Scan Left to right; Up to Down
for (int y = 0; y < image.getHeight(); y++) {
for (int x = 0; x < image.getWidth(); x++) {
  int clr = image.getRGB(x, y);
  int red = (clr & 0x00ff0000) >> 16;
  int green = (clr & 0x0000ff00) >> 8;
  int blue = clr & 0x000000ff;
  int alpha = (clr & 0xff000000) >>> 24;

  writer.write(lengths[y][x] & 255);
  writer.write((lengths[y][x] >> 8) &  255);
  writer.write(red);
  writer.write(green);
  writer.write(blue);
  writer.write(alpha);
}
}
And the Lua:
local fileName = "input"
-- Glasses Bridge Side
local side = "top"
local g = peripheral.wrap(side)
local lastTime = os.clock()
local queueEvent = os.queueEvent
local pullEvent = os.pullEvent
local myEvent
local addBox = g.addBox
local sync = g.sync
local function b(x,y,leng,hex,opacity)
  addBox(x,y,leng,1,hex,opacity)
end
g.clear()
local input = fs.open(fileName, "rb")
local read = input.read
volumes = read()
local height = read() + read() * 256
local width = read() + read() * 256
local heighty
local widthy
for heighty=0, height-1 do
  for widthy=0, width-1 do
	--local r,g,b,a = input.read(),input.read(),input.read(),input.read()
	b(widthy,heighty,read() + read() * 256,((read()*65536)+(read()*256))+read(),read()*0.00392156863)
	myEvent = tostring({})
	queueEvent(myEvent)
	pullEvent(myEvent)
  end
end
print("T: "..os.clock()-lastTime) --Takes 53.3 seconds using a moderately intensive image
input.close()
g.sync()
My only issue now is that it is still super slow. I skimmed through this handy guide and took anything that could apply to JLua but it still isn't that quick. Is it even possible to go faster?



#274571 Computercraft processing bytes weirdly

Posted by olie304 on 18 January 2018 - 06:32 PM in Ask a Pro

View PostBomb Bloke, on 15 January 2018 - 01:50 AM, said:


I might end up using single framed GIFs and your decoder because of how fast it is. I already have a PNG decoder written in Java if you want to take a look at it. The problem I have is reading it and reading it fast on CC's side. I offset everything by a value of 32 because for some reason any bytes before 32 automatically have a value of 32.
import java.io.*;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.ArrayList;
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;

public class ImageToGlasses {

public static String pointToByte(int codePoint, int offset) {
  String bytes = "";
  byte[] b = {
   (byte)(codePoint + offset)
  };
  bytes = new String(b, StandardCharsets.ISO_8859_1);
  return bytes;
}

public static String hexToByte(String hexString) {
  int val = Integer.parseInt(hexString, 16);
  String bytes = "";
  byte[] b = {
   (byte)((val >>> 24) & 0xff),
   (byte)((val >>> 16) & 0xff),
   (byte)((val >>> 8) & 0xff),
   (byte)((val >>> 0) & 0xff)
  };
  bytes = new String(b, StandardCharsets.ISO_8859_1);
  return bytes;
}

public static void main(String args[]) throws IOException {

  //Output file
  String outputName = "out";

  //Input PNG or JPG
  String fileName = "image.png";

  if (args.length == 1) {
   outputName = args[1];
   fileName = args[0];
  } else {
   System.out.println("Ex: java -jar ImageToGlasses.jar image.png outputFile");
  }

  ArrayList < String > bytes = new ArrayList < String > ();

  File file = new File(fileName);
  BufferedImage image = ImageIO.read(file);
  Files.deleteIfExists(Paths.get(outputName));

  BufferedWriter writer = Files.newBufferedWriter(Paths.get(outputName), StandardCharsets.UTF_8);
  writer.write("!"); //Default file header, defines the number of volumes that need to be read. E.x. "!" = (Code Point)33 - 32(Offset) = 1 Volume

  //Scan Left to right; Up to Down
  for (int y = 0; y < image.getHeight(); y++) {
   for (int x = 0; x < image.getWidth(); x++) {

	int clr = image.getRGB(x, y);
	int red = (clr & 0x00ff0000) >> 16;
	int green = (clr & 0x0000ff00) >> 8;
	int blue = clr & 0x000000ff;
	int alpha = (clr & 0xff000000) >>> 24;

	String hex = String.format("%02X%02X%02X", red, green, blue);

	//Add a box to the array
	if (alpha > 0 && !hex.equals("000000")) {
	 bytes.add(pointToByte(x, 32));
	 bytes.add(pointToByte(y, 32));
	 bytes.add(pointToByte(boxLeng, 32));
	 bytes.add(hexToByte(hex));
	 bytes.add(pointToByte(alpha, 32));
	}
   }

   for (int i = 0; i < bytes.size(); i++) {
	writer.write(bytes.get(i));
   }
  
   writer.close();
  }
}

Here is the entire Lua code that I use to decode the new format



#274369 Computercraft processing bytes weirdly

Posted by olie304 on 14 January 2018 - 07:23 PM in Ask a Pro

View PostBomb Bloke, on 13 January 2018 - 03:17 PM, said:


This is actually a continuation to my project that displays an image on the Open Peripherals terminal glasses. I put this issue in a new topic because it is a completely different approach on what I was doing before and brought up a specific problem I could not find the answer to. I managed to make a file format that puts the number of files as a byte first, then each pixel or block of pixels has the (x,y), length of block, hex color, and then opacity. I am doing it this way because I could not figure out how to parse an actual png file in lua. The way I am doing it takes a looooonnggg time to process an image. Is there something I can read up on that says how certain binary formats are setup and organized?



#274349 Computercraft processing bytes weirdly

Posted by olie304 on 13 January 2018 - 07:00 AM in Ask a Pro

View PostBomb Bloke, on 05 January 2018 - 06:14 AM, said:


Can you go more in depth on this? How do things like your GIF API or BBpack compression work when it comes to binary data?



#274107 Computercraft processing bytes weirdly

Posted by olie304 on 04 January 2018 - 09:28 PM in Ask a Pro

Lately I have been having issues with the way Computercraft reads and processes bytes in a file. I am on an older version of CC (1.7.10) so I do not have access to the byte reading modes. What I think happens is it skips some bytes and then merges them with others for some reason. When using Mimic or repl.it with my same program it works just fine, but, using the ingame system gives the strange results. Here is some data for comparison:

(Byte Val, Hex Val, Char Size)
- Output from the computer ingame
Posted Image

(Byte Val, Hex Val, Char Size)
- Output from Mimic
Posted Image


+ Actual values:

- Hexadecimal (in UTF-8 encoding)
Posted Image
- Characters (in UTF-8 encoding)
Posted Image
- Characters (in browser, probably also UTF-8 for you)
!— ! ÿª #


- Code: https://pastebin.com/pzWiQPfD (UTF-8 decoding snippets taken from https://github.com/Stepets/utf8.lua)

Is this an encoding issue or coding issue? I am not too knowledgeable with encodings so the file on my computer could be using the wrong encoding thus causing the issue. Thanks.



#271823 Image to Terminal glasses efficiency

Posted by olie304 on 13 November 2017 - 11:08 PM in Ask a Pro

View PostBomb Bloke, on 13 November 2017 - 06:33 AM, said:

The image data you've generated seems to be rendering correctly. The issue is in your (omitted) Java code: it's setting box[4] to 0 for each and every record.

(In cases where it should be set to 0, I personally wouldn't define it at all.)

Your duped pixel checker is also still broken, there are a lot of savings to be made by fixing that!
Sorry if I didn't clear this up, I am aware of the other bugs which I plan on fixing but I am having a lot of trouble with a new issue. I have worked on it a bit but the only fix I can make is an output line like this
{0,187,{1,0xFF5000},{53,0xFF5000},{1,0xFF5000,0.2},{1},{106},{1,0x00AEEF},{145,0x00AEEF},{1},{169},{1,0x00FF00},{1,0x00FF00}},
English translation: Start line at X=0,Y=187. Add 1 colored box with a length of 0 then one after with a length of 52 then another after with a length of 1. Next add an empty space after for 106 pixels. E.t.c.
From above, I mentioned the reason box[4] existed was to make up for the transparent pixels. In the example line from this post I have omitted box[4] entirely just added the location a box of transparent pixels starts: like {169} which has no other data. The lua now does this:
if #box == 3 then
b(x, y, box[1], box[2], box[3])
elseif(#box == 2) then
b(x, y, box[1], box[2], 1.0) -- Idea from calling out the repetitive 0s. Now every, very common, fully colored pixel no longer needs to be defined.
end
x = x + box[1]
My problem is that whenever I try to add the length of the transparent pixels to another piece of data it should read (i.e. box[4]) then it distorts even more.

p.s. I disabled the code that assigns box[4] in the example you saw so I could create the two example files.



#271806 Gradient Rainbow lamps (Thermal Expansion)

Posted by olie304 on 13 November 2017 - 12:14 AM in Programs

pastebin get 85MwvYUD RainbowLampsLinear


pastebin get z0MEDxsV RainbowLampsRandom

Simply makes it so that lumium lamps from Thermal Expansion gradiently go across the rainbow. If you use the linear program the direction of the rainbow will be in the order that you activate the modems on the back of the lamps. Enjoy!

Posted ImagePosted Image



#271805 Image to Terminal glasses efficiency

Posted by olie304 on 12 November 2017 - 11:10 PM in Ask a Pro

View PostBomb Bloke, on 08 November 2017 - 05:51 AM, said:

That sounds... unlikely. I mean, yeah, direct calls will technically execute faster than ones requiring table lookups... but 120x faster? No, I'd say there was something very wrong with your implementation.
Seems like you are right, using nested arrays for this works way better, however I am having a difficult time making the final image not distorted. It seems that when it deals with a transparent file, since I do not include the fully transparent pixels to save space, it ends up placing everything that is on the same line right next to each other. I have tried accounting for the transparent pixels by adding an extra length element, but nothing I do seems to work correctly: either everything gets moved or nothing gets moved. I have been trying to count up the amount of spaces with clear pixels in-between each colored one and then add it to the X value along with the box size.

It should look like this: (image), however without changing anything it looks like this: (image) (output code), and if I add a counter to add a space between two colored pixels it looks like this: (image). It works fine if I re-include the transparent pixels but of course this isn't optimal. Any idea on what's happening here?



#271671 Image to Terminal glasses efficiency

Posted by olie304 on 08 November 2017 - 12:53 AM in Ask a Pro

View PostBomb Bloke, on 06 November 2017 - 03:04 AM, said:

When searching for duped pixels, it'd be easier to look at the next color for matches, not the previous colour. If you really want to check the previous colour then you'll need to jump through a few hoops in order to avoid generating stuff like this within your output:

b(22,207,1,0x010101,1.0)
b(23,207,3,0x010101,1.0)

Checking for duped pixels in two dimensions might be a bit tricky, but it may not be too painful to perform an initial count-up to find the "most common colour" before you do your main draw. That colour can then be plonked down as one big box (assuming it doesn't turn out to be "full transparency"), effectively making it a "background".

You could stand to drop the precision on your alpha values a bit (just round to the nearest hundredth), and there's certainly no call for any "point zeroes". You could also ignore the lowest bit of your R/G/B values when doing comparisons - this probably wouldn't reduce visual quality by any noticeable amount, but it'd potentially save a lot of space.

The largest reduction would be to make your code just a little more complex. Instead of generating a million lines of function calls with nearly identical x/y co-ords baked into them, generate a table with just the raw data you need, then use a Lua loop structure to do the actual drawing. Eg:

Spoiler

Really I don't see any great reason to duplicate the "executable code" within every single "data file" you produce, though. You could again get another large reduction in filesize by switching to a "binary" output format and keeping your "image drawing" script code in a single stand-alone file.

BBPack may be useful here. Entering "bbpack compress" at the command line, and then adding os.loadAPI("bbpack") to the top of your startup file, will typically allow you to store a lot more on your computers. You can likewise do "bbpack <URL> <localPath>" to create links to online sources from within your local filesystem, making it easy to work with files which're potentially much larger than what your drives could hold.

Using bbpack is a good idea, it has solved a lot of my problems in the past. I am afraid of using a loop or reading a raw binary image because of how slow it will be. From previous attempts it took up to 30 minutes to load a 480p image that can be loaded in 15 seconds using a jillion billion method calls.



#271587 Image to Terminal glasses efficiency

Posted by olie304 on 05 November 2017 - 11:11 PM in Ask a Pro

Thanks guys, I will be trying out some of those things soon. Here is an example output http://auraxium.com/Examples/ (they exceed 500k so I have them on my site)



#271580 Image to Terminal glasses efficiency

Posted by olie304 on 05 November 2017 - 07:32 PM in Ask a Pro

Hello everyone, I made a small script in Java that converts any image to a program that can be ran with Terminal Glasses from Open Peripherals. It works great however I have encountered some issues: It takes a while to load the image and causes a lag spike whilst doing so, The program can crash people who use a large enough image (or smaller ones that are 480x270 in some cases) if they are running a potato, and the files are immensely large.

To combat these issues I have tried: Making a color palette and using a loop to create each pixel which resulted in a longer load time, Making a list of colors and then a loop which increased the file size and made the load longer, Making the script produce multiple volumes that get taken off my server so the program could fit on a computer which works but it isn't optimal, and I have tried cutting out as much fat as possible by making similar pixels on the X axis one block and by using functions to minimize the length of repeated variables and methods to one character; this has also helped a lot.

Is there anything I am missing? At the very least I want to make a system for similar pixels on the Y axis to be turned into one block but I do not know how to approach this correctly, and if I am a little ambitious it would be good to have the output fit into one or two files.

Thanks.

Code:
import java.io.*;
import java.nio.file.Files;
import java.nio.file.Paths;
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;

public class ImageToGlasses {

public static void main(String args[]) throws IOException {

//Horizontal size of a box with the same pixel colors
  int boxLeng = 1;

//Should it reboot once done writing to peripheral?
  boolean startupProgram = false;

//Current line of output file, resets every 21600 lines
  int currentLine = 0;

//Keep scanning down X for similar pixel color?
  boolean keepGoing = true;

//Previous color down X to test similar color
  int prevColor = 0;

//Number of files created
  int fileNo = 0;

//Output program
  String outputName = "outFile";

//Input PNG or JPG
  String fileName = "inImage.png";


  if(args.length == 1) {
   outputName = args[1];
   fileName = args[0];
  }else{
   System.out.println("Ex: java -jar ImageToGlasses.jar image.png outputLua");
  }


  File file = new File(fileName);
  BufferedImage image = ImageIO.read(file);

  Files.deleteIfExists(Paths.get(outputName));

  BufferedWriter writer = new BufferedWriter(new FileWriter(outputName, true));

//Write a header
  writer.append("g = peripheral.wrap(\"top\")\n");
  writer.append("function b(x,y,leng,hex,opacity)\n");
  writer.append("g.addBox(x,y,leng,1,hex,opacity)\n");
  writer.append("end\n");
  writer.append("g.clear()\n");

//Scan Left to right; Up to Down
  for (int y = 0; y < image.getHeight(); y++) {
   for (int x = 0; x < image.getWidth(); x++) {

	int clr = image.getRGB(x, y);
	int red = (clr & 0x00ff0000) >> 16;
	int green = (clr & 0x0000ff00) >> 8;
	int blue = clr & 0x000000ff;
	int alpha = (clr & 0xff000000) >>> 24;
	String hex = String.format("0x%02X%02X%02X", red, green, blue);

//Is the last pixel down X the same as the current one? If so extend length of box
	if (prevColor == clr) {

	 keepGoing = true;
	 for (int ex = x; ex < image.getWidth() && keepGoing; ex++) {

	  if (image.getRGB(ex, y) == prevColor) {

	   boxLeng++;

	  } else {

	   keepGoing = false;

	  }
	 }
	}

	prevColor = clr;

//Use opacity if applicable, Prevents the writing of fully transparent pixels to save space
	if (((Integer) alpha).doubleValue() / 255.0 > 0.0) {

	 writer.append("b(" + x + "," + y + "," + boxLeng + "," + hex + "," + (((Integer) alpha).doubleValue() / 255.0) + ")\n");

	}
  
//When there are similar pixels start scanning X after the box
	if (boxLeng > 1) {

	 x = x + boxLeng - 1;

	}

	boxLeng = 1;

//Limit the file size, checks every 21600 lines to see if it's larger than ~500KB
	if (currentLine == 21600) {

	 boolean createNewFile = false;
	 currentLine = 0;
	 writer.close();

	 if (fileNo == 0) {

	  if (Files.size(Paths.get(outputName)) >= 300000) {

	   createNewFile = true;
	   writer = new BufferedWriter(new FileWriter(outputName, true));

	  } else {

	   writer = new BufferedWriter(new FileWriter(outputName, true));

	  }

	 } else {

	  if (Files.size(Paths.get(outputName + fileNo)) >= 300000) {

	   createNewFile = true;
	   writer = new BufferedWriter(new FileWriter(outputName + fileNo, true));

	  } else {

	   writer = new BufferedWriter(new FileWriter(outputName + fileNo, true));

	  }
	 }
	
//Check if file exceeded max size, closes writer and starts a new one
	 if (createNewFile) {

	  fileNo++;
	  writer.append("shell.run(\"paster run " + outputName + fileNo + "\")");
	  writer.close();
	  Files.deleteIfExists(Paths.get(outputName + fileNo));
	  writer = new BufferedWriter(new FileWriter(outputName + fileNo, true));

	  writer.append("g = peripheral.wrap(\"top\")\n");
	  writer.append("function b(x,y,leng,hex,opacity)\n");
	  writer.append("g.addBox(x,y,leng,1,hex,opacity)\n");
	  writer.append("end\n");

	 }
	}

	currentLine++;

   }
  }

//Add footer when done with current file
  writer.append("g.sync()\n");

  if (startupProgram) {
   writer.append("shell.run(\"startup\")");
  }

  writer.close();

}
}



#271202 Parse hexadecimal value from string

Posted by olie304 on 25 October 2017 - 02:49 AM in Ask a Pro

thx m8



#271186 Parse hexadecimal value from string

Posted by olie304 on 24 October 2017 - 02:22 AM in Ask a Pro

Hello everyone, currently trying to make a program that gradiently cycles through many hexadecimal values to cause a cool gradient effect on the Radiant Lamp from thermal expansion. However the code I use for changing my rgb value to a hex value returns the hex value as a string, which is no bueno and gives an error when trying to use it as a color. I don't have this problem a lot because my hex values are usually predefined but I do not know how to parse a hex value from the string.

Code:
local radiantLamp = peripheral.wrap("back")

function rgbToHex(rgb)
	local hexadecimal = '0x'

	for key, value in pairs(rgb) do
		local hex = ''

		while(value > 0)do
			local index = math.fmod(value, 16) + 1
			value = math.floor(value / 16)
			hex = string.sub('0123456789ABCDEF', index, index) .. hex		
		end

		if(string.len(hex) == 0)then
			hex = '00'

		elseif(string.len(hex) == 1)then
			hex = '0' .. hex
		end

		hexadecimal = hexadecimal .. hex
	end

	return hexadecimal
end

local time = 0

while true do
local frequency = 0.3
local red = math.sin(frequency*time + 0) * 127 + 128
local green = math.sin(frequency*time + 2) * 127 + 128
local blue = math.sin(frequency*time + 4) * 127 + 128

local hexColor = rgbToHex({red,green,blue})

radiantLamp.setColor(hexColor)
time++
end

Exact error:
38: Failed to convert arg 'color', cause: 'No known conversion of value 0x80F31F to int'

Thanks.



#270242 Download PNG for CCLights2; Weird encoding?

Posted by olie304 on 12 September 2017 - 05:06 AM in Ask a Pro

Hi, I am currently trying to download a picture off of my web server or the internet in general for usage on CCLights2 Monitors. The file downloads but for some reason it isn't a complete file (probably some kinda encoding issue somewhere). The file size is usually almost the same except off by a few bytes. When looking at the file in the programs folder windows just tells me it is a corrupted file.

I have been using something like this:

local file = fs.open("logo.png","w")
img = http.get("http://testsite.net/logo.png")
out = img.readAll()
img.close()
file.write(out)
file.close()
gpu = peripheral.wrap("right")

local lp = fs.combine(shell.getRunningProgram(),"..")
  fs.copy(fs.combine(lp,"logo.png"),"temp.png")
  local t = gpu.import("temp.png")
  fs.delete("temp.png")
  gpu.setColor(255,255,255)
  gpu.drawTexture(t,0,0)
  gpu.freeTexture(t)
 

But that didn't work. It gave an error (Don't know what it was because I re-created the PG and don't get any errors) so after some "intense" googling I found someone with a similar issue and tried their fix:

local response = http.get("https://www.google.com/images/srpr/logo3w.png")

if response then  local sResponse = response.readAll()
  response.close()
 
  local file = fs.open("file.png", "wb")
 
 
  for i = 1, #sResponse do
 
    file.write(string.byte(sResponse, i))
  end
 
  file.close()
 
end
local lp = fs.combine(shell.getRunningProgram(),"..")
fs.copy(fs.combine(lp,"file.png"),"temp.png")local t = gpu.import("temp.png")
fs.delete("temp.png")gpu.setColor(255,255,255)
gpu.drawTexture(t,0,0)
gpu.freeTexture(t)

All this does is runs with no errors and doesn't display anything.

Side note: Does anyone know where to find a good version of CCLights2? I tried the download on their main thread (github) and it only shows a blank white screen which sometimes has a colored box if you run the example program but not always. Their jenkins page is restricted now. There was a reply on the main thread which had the version I am using now that is pretty buggy but at least it is usable